Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stevedonovan/Penlight.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThijs Schreijer <thijs@thijsschreijer.nl>2018-11-22 18:41:22 +0300
committerThijs Schreijer <thijs@thijsschreijer.nl>2018-11-23 23:08:28 +0300
commitd70ac91eede03936db36b3fc31b62500242ed2e7 (patch)
tree20971375fd99be2b663b0379b58b9c2484debcda
parent2615db2914b46376a08e6045776e2206da390589 (diff)
Release 1.6.01.6.0
Moved docs to ./docs for easy github publishing Also added and fixed some additional links in the readme.
-rw-r--r--CHANGELOG.md5
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--README.md17
-rw-r--r--config.ld (renamed from doc/config.ld)13
-rw-r--r--docs/classes/pl.Date.html1041
-rw-r--r--docs/classes/pl.List.html1444
-rw-r--r--docs/classes/pl.Map.html419
-rw-r--r--docs/classes/pl.MultiMap.html208
-rw-r--r--docs/classes/pl.OrderedMap.html418
-rw-r--r--docs/examples/seesubst.lua.html175
-rw-r--r--docs/examples/sipscan.lua.html162
-rw-r--r--docs/examples/symbols.lua.html348
-rw-r--r--docs/examples/test-cmp.lua.html131
-rw-r--r--docs/examples/test-data.lua.html373
-rw-r--r--docs/examples/test-listcallbacks.lua.html139
-rw-r--r--docs/examples/test-pretty.lua.html141
-rw-r--r--docs/examples/test-symbols.lua.html210
-rw-r--r--docs/examples/testapp.lua.html133
-rw-r--r--docs/examples/testclone.lua.html166
-rw-r--r--docs/examples/testconfig.lua.html177
-rw-r--r--docs/examples/testglobal.lua.html154
-rw-r--r--docs/examples/testinputfields.lua.html141
-rw-r--r--docs/examples/testinputfields2.lua.html137
-rw-r--r--docs/examples/testxml.lua.html210
-rw-r--r--docs/examples/which.lua.html156
-rw-r--r--docs/index.html394
-rw-r--r--docs/ldoc_fixed.css311
-rw-r--r--docs/libraries/pl.Set.html650
-rw-r--r--docs/libraries/pl.app.html310
-rw-r--r--docs/libraries/pl.array2d.html1151
-rw-r--r--docs/libraries/pl.class.html333
-rw-r--r--docs/libraries/pl.compat.html372
-rw-r--r--docs/libraries/pl.comprehension.html166
-rw-r--r--docs/libraries/pl.config.html254
-rw-r--r--docs/libraries/pl.data.html570
-rw-r--r--docs/libraries/pl.dir.html613
-rw-r--r--docs/libraries/pl.file.html378
-rw-r--r--docs/libraries/pl.func.html461
-rw-r--r--docs/libraries/pl.html140
-rw-r--r--docs/libraries/pl.import_into.html143
-rw-r--r--docs/libraries/pl.input.html333
-rw-r--r--docs/libraries/pl.lapp.html383
-rw-r--r--docs/libraries/pl.lexer.html525
-rw-r--r--docs/libraries/pl.luabalanced.html150
-rw-r--r--docs/libraries/pl.operator.html812
-rw-r--r--docs/libraries/pl.path.html900
-rw-r--r--docs/libraries/pl.permute.html210
-rw-r--r--docs/libraries/pl.pretty.html345
-rw-r--r--docs/libraries/pl.seq.html889
-rw-r--r--docs/libraries/pl.sip.html400
-rw-r--r--docs/libraries/pl.strict.html254
-rw-r--r--docs/libraries/pl.stringio.html216
-rw-r--r--docs/libraries/pl.stringx.html1162
-rw-r--r--docs/libraries/pl.tablex.html1895
-rw-r--r--docs/libraries/pl.template.html334
-rw-r--r--docs/libraries/pl.test.html432
-rw-r--r--docs/libraries/pl.text.html378
-rw-r--r--docs/libraries/pl.types.html412
-rw-r--r--docs/libraries/pl.url.html201
-rw-r--r--docs/libraries/pl.utils.html1179
-rw-r--r--docs/libraries/pl.xml.html836
-rw-r--r--docs/manual/01-introduction.md.html845
-rw-r--r--docs/manual/02-arrays.md.html911
-rw-r--r--docs/manual/03-strings.md.html397
-rw-r--r--docs/manual/04-paths.md.html330
-rw-r--r--docs/manual/05-dates.md.html266
-rw-r--r--docs/manual/06-data.md.html1638
-rw-r--r--docs/manual/07-functional.md.html835
-rw-r--r--docs/manual/08-additional.md.html816
-rw-r--r--docs/manual/09-discussion.md.html232
-rw-r--r--docs_topics/01-introduction.md (renamed from doc/manual/01-introduction.md)0
-rw-r--r--docs_topics/02-arrays.md (renamed from doc/manual/02-arrays.md)0
-rw-r--r--docs_topics/03-strings.md (renamed from doc/manual/03-strings.md)0
-rw-r--r--docs_topics/04-paths.md (renamed from doc/manual/04-paths.md)0
-rw-r--r--docs_topics/05-dates.md (renamed from doc/manual/05-dates.md)0
-rw-r--r--docs_topics/06-data.md (renamed from doc/manual/06-data.md)0
-rw-r--r--docs_topics/07-functional.md (renamed from doc/manual/07-functional.md)0
-rw-r--r--docs_topics/08-additional.md (renamed from doc/manual/08-additional.md)0
-rw-r--r--docs_topics/09-discussion.md (renamed from doc/manual/09-discussion.md)0
-rw-r--r--lua/pl/utils.lua2
-rw-r--r--penlight-scm-2.rockspec (renamed from penlight-scm-1.rockspec)4
-rw-r--r--tests/test-dir.lua8
-rw-r--r--tests/test-path.lua8
83 files changed, 31278 insertions, 26 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3db742..161a7a4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# Changelog
-## 1.6.0 (not released yet)
+## 1.6.0 (2018-11-23)
### New features
@@ -10,6 +10,7 @@
- `utils.unpack` is now documented and respects `.n` field of its argument.
- `tablex.deepcopy` and `tablex.deepcompare` are now cycle aware (#262)
+ - Installing through LuaRocks will now include the full rendered documentation
### Fixes
@@ -29,7 +30,7 @@
### Fixes
- - Fixed `compat.execute` behaving differently on Lua 5.1 and 5,1+.
+ - Fixed `compat.execute` behaving differently on Lua 5.1 and 5.1+.
- Fixed `lapp.process_options_string` setting global `success` variable.
## 1.5.3 (2017-07-16)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 90ea9e4..0ec775d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -34,7 +34,7 @@ you're doing, such as _"added-klingon-cloacking-device"_ - from `master` branch.
If you wanna be a rockstar;
-1. Update the [CHANGES.md](https://github.com/stevedonovan/Penlight/blob/master/CHANGES.md) file
+1. Update the [CHANGELOG.md](https://github.com/stevedonovan/Penlight/blob/master/CHANGELOG.md) file
2. [Add tests](https://github.com/stevedonovan/Penlight/tree/master/tests) that show the defect your fix repairs, or that tests your new feature
Please note - if you want to change multiple things that don't depend on each
diff --git a/README.md b/README.md
index ef9095a..99e966e 100644
--- a/README.md
+++ b/README.md
@@ -57,6 +57,10 @@ Python standard libraries.
* `utils`: `utils.string_lambda` converts short strings like '|x| x^2' into functions
* `comprehension`: list comprehensions: `C'x for x=1,4'()=={1,2,3,4}`
+## License
+
+Penlight is distributed under the [MIT license](https://github.com/stevedonovan/Penlight/blob/master/LICENSE.md)
+
## Installation
Using [LuaRocks](https://luarocks.org): simply run `luarocks install penlight`.
@@ -75,12 +79,17 @@ in Lua for Windows.
## Building the Documentation
Requires [ldoc](https://github.com/stevedonovan/LDoc), which is available
-through LuaRocks. Then it's a simple matter of running `ldoc` in the docs folder.
+through LuaRocks. Then it's a simple matter of running `ldoc .` from the repo.
+
+## Contributing
-```
-Penlight/docs$ ldoc .
-```
+Contributions are most welcome, please check the [contribution guidelines](https://github.com/stevedonovan/Penlight/blob/master/CONTRIBUTING.md).
## Running tests
Execute `lua run.lua tests` to run the tests. Execute `lua run.lua examples` to run examples.
+
+## History
+
+For a complete history of the development of Penlight, please check the
+[changelog](https://github.com/stevedonovan/Penlight/blob/master/CHANGELOG.md).
diff --git a/doc/config.ld b/config.ld
index da115cb..e56ed2d 100644
--- a/doc/config.ld
+++ b/config.ld
@@ -1,20 +1,17 @@
project = 'Penlight'
-description = 'Penlight Lua Libraries 1.5.4'
+description = 'Penlight Lua Libraries 1.6.0'
full_description = 'The documentation is available @{01-introduction.md|here}.'
title = 'Penlight Documentation'
-dir = 'api'
+dir = 'docs'
style = '!fixed'
use_markdown_titles = true
-topics = 'manual'
-examples = {'../examples','../tests/test-data.lua'}
+topics = 'docs_topics'
+examples = {'./examples','./tests/test-data.lua'}
package = 'pl'
format = 'discount'
sort_modules=true
-file = '../lua/pl'
+file = './lua/pl'
kind_names={topic='Manual',module='Libraries'}
tparam_alias('array','array')
tparam_alias('array2d','array')
alias('ret',{'return',modifiers={type="$1"}})
-
-
-
diff --git a/docs/classes/pl.Date.html b/docs/classes/pl.Date.html
new file mode 100644
index 0000000..2f35b94
--- /dev/null
+++ b/docs/classes/pl.Date.html
@@ -0,0 +1,1041 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+<li><a href="#Methods">Methods</a></li>
+</ul>
+
+
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><strong>pl.Date</strong></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Class <code>pl.Date</code></h1>
+<p>Date and Date Format classes.</p>
+<p> See <a href="../manual/05-dates.md.html#">the Guide</a>.</p>
+
+<p> Dependencies: <a href="../libraries/pl.class.html#">pl.class</a>, <a href="../libraries/pl.stringx.html#">pl.stringx</a>, <a href="../libraries/pl.utils.html#">pl.utils</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#Date:set">Date:set (t)</a></td>
+ <td class="summary">set the current time of this Date object.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date.tzone">Date.tzone (ts)</a></td>
+ <td class="summary">get the time zone offset from UTC.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:toUTC">Date:toUTC ()</a></td>
+ <td class="summary">convert this date to UTC.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:toLocal">Date:toLocal ()</a></td>
+ <td class="summary">convert this UTC date to local.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:year">Date:year (y)</a></td>
+ <td class="summary">set the year.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:month">Date:month (m)</a></td>
+ <td class="summary">set the month.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:day">Date:day (d)</a></td>
+ <td class="summary">set the day.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:hour">Date:hour (h)</a></td>
+ <td class="summary">set the hour.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:min">Date:min (min)</a></td>
+ <td class="summary">set the minutes.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:sec">Date:sec (sec)</a></td>
+ <td class="summary">set the seconds.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:yday">Date:yday (yday)</a></td>
+ <td class="summary">set the day of year.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:year">Date:year (y)</a></td>
+ <td class="summary">get the year.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:month">Date:month ()</a></td>
+ <td class="summary">get the month.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:day">Date:day ()</a></td>
+ <td class="summary">get the day.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:hour">Date:hour ()</a></td>
+ <td class="summary">get the hour.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:min">Date:min ()</a></td>
+ <td class="summary">get the minutes.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:sec">Date:sec ()</a></td>
+ <td class="summary">get the seconds.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:yday">Date:yday ()</a></td>
+ <td class="summary">get the day of year.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:weekday_name">Date:weekday_name (full)</a></td>
+ <td class="summary">name of day of week.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:month_name">Date:month_name (full)</a></td>
+ <td class="summary">name of month.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:is_weekend">Date:is_weekend ()</a></td>
+ <td class="summary">is this day on a weekend?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:add">Date:add (t)</a></td>
+ <td class="summary">add to a date object.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:last_day">Date:last_day ()</a></td>
+ <td class="summary">last day of the month.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:diff">Date:diff (other)</a></td>
+ <td class="summary">difference between two Date objects.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:__tostring">Date:__tostring ()</a></td>
+ <td class="summary">long numerical ISO data format version of this date.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:__eq">Date:__eq (other)</a></td>
+ <td class="summary">equality between Date objects.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:__lt">Date:__lt (other)</a></td>
+ <td class="summary">ordering between Date objects.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:__sub">Date:__sub ()</a></td>
+ <td class="summary">difference between Date objects.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date:__add">Date:__add (other)</a></td>
+ <td class="summary">add a date and an interval.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date.Interval">Date.Interval (t)</a></td>
+ <td class="summary">Date.Interval constructor</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date.Interval:__tostring">Date.Interval:__tostring ()</a></td>
+ <td class="summary">If it&rsquo;s an interval then the format is &lsquo;2 hours 29 sec&rsquo; etc.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date.Format">Date.Format (fmt.)</a></td>
+ <td class="summary">Date.Format constructor.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date.Format:parse">Date.Format:parse (str)</a></td>
+ <td class="summary">parse a string into a Date object.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date.Format:tostring">Date.Format:tostring (d)</a></td>
+ <td class="summary">convert a Date object into a string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Date.Format:US_order">Date.Format:US_order (yesno)</a></td>
+ <td class="summary">force US order in dates like 9/11/2001</td>
+ </tr>
+</table>
+<h2><a href="#Methods">Methods</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#pl.Date:Date">pl.Date:Date (t, ...)</a></td>
+ <td class="summary">Date constructor.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "Date:set"></a>
+ <strong>Date:set (t)</strong>
+ </dt>
+ <dd>
+ set the current time of this Date object.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">int</span></span>
+ seconds since epoch
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date.tzone"></a>
+ <strong>Date.tzone (ts)</strong>
+ </dt>
+ <dd>
+ get the time zone offset from UTC.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">ts</span>
+ <span class="types"><span class="type">int</span></span>
+ seconds ahead of UTC
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:toUTC"></a>
+ <strong>Date:toUTC ()</strong>
+ </dt>
+ <dd>
+ convert this date to UTC.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:toLocal"></a>
+ <strong>Date:toLocal ()</strong>
+ </dt>
+ <dd>
+ convert this UTC date to local.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:year"></a>
+ <strong>Date:year (y)</strong>
+ </dt>
+ <dd>
+ set the year.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">y</span>
+ <span class="types"><span class="type">int</span></span>
+ Four-digit year
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:month"></a>
+ <strong>Date:month (m)</strong>
+ </dt>
+ <dd>
+ set the month.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">m</span>
+ <span class="types"><span class="type">int</span></span>
+ month
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:day"></a>
+ <strong>Date:day (d)</strong>
+ </dt>
+ <dd>
+ set the day.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">d</span>
+ <span class="types"><span class="type">int</span></span>
+ day
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:hour"></a>
+ <strong>Date:hour (h)</strong>
+ </dt>
+ <dd>
+ set the hour.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">h</span>
+ <span class="types"><span class="type">int</span></span>
+ hour
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:min"></a>
+ <strong>Date:min (min)</strong>
+ </dt>
+ <dd>
+ set the minutes.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">min</span>
+ <span class="types"><span class="type">int</span></span>
+ minutes
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:sec"></a>
+ <strong>Date:sec (sec)</strong>
+ </dt>
+ <dd>
+ set the seconds.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">sec</span>
+ <span class="types"><span class="type">int</span></span>
+ seconds
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:yday"></a>
+ <strong>Date:yday (yday)</strong>
+ </dt>
+ <dd>
+ set the day of year.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">yday</span>
+ <span class="types"><span class="type">int</span></span>
+ day of year
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:year"></a>
+ <strong>Date:year (y)</strong>
+ </dt>
+ <dd>
+ get the year.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">y</span>
+ <span class="types"><span class="type">int</span></span>
+ Four-digit year
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:month"></a>
+ <strong>Date:month ()</strong>
+ </dt>
+ <dd>
+ get the month.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:day"></a>
+ <strong>Date:day ()</strong>
+ </dt>
+ <dd>
+ get the day.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:hour"></a>
+ <strong>Date:hour ()</strong>
+ </dt>
+ <dd>
+ get the hour.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:min"></a>
+ <strong>Date:min ()</strong>
+ </dt>
+ <dd>
+ get the minutes.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:sec"></a>
+ <strong>Date:sec ()</strong>
+ </dt>
+ <dd>
+ get the seconds.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:yday"></a>
+ <strong>Date:yday ()</strong>
+ </dt>
+ <dd>
+ get the day of year.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:weekday_name"></a>
+ <strong>Date:weekday_name (full)</strong>
+ </dt>
+ <dd>
+ name of day of week.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">full</span>
+ <span class="types"><span class="type">bool</span></span>
+ abbreviated if true, full otherwise.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ name
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:month_name"></a>
+ <strong>Date:month_name (full)</strong>
+ </dt>
+ <dd>
+ name of month.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">full</span>
+ <span class="types"><span class="type">int</span></span>
+ abbreviated if true, full otherwise.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ name
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:is_weekend"></a>
+ <strong>Date:is_weekend ()</strong>
+ </dt>
+ <dd>
+ is this day on a weekend?.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:add"></a>
+ <strong>Date:add (t)</strong>
+ </dt>
+ <dd>
+ add to a date object.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table containing one of the following keys and a value:
+ one of <a href="../classes/pl.Date.html#Date:year">year</a>,<a href="../classes/pl.Date.html#Date:month">month</a>,<a href="../classes/pl.Date.html#Date:day">day</a>,<a href="../classes/pl.Date.html#Date:hour">hour</a>,<a href="../classes/pl.Date.html#Date:min">min</a>,<a href="../classes/pl.Date.html#Date:sec">sec</a>
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ this date
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:last_day"></a>
+ <strong>Date:last_day ()</strong>
+ </dt>
+ <dd>
+ last day of the month.
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ int day
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:diff"></a>
+ <strong>Date:diff (other)</strong>
+ </dt>
+ <dd>
+ difference between two Date objects.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">other</span>
+ <span class="types"><a class="type" href="../classes/pl.Date.html">Date</a></span>
+ Date object
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="../classes/pl.Date.html#Date.Interval">Date.Interval</a></span>
+ object
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:__tostring"></a>
+ <strong>Date:__tostring ()</strong>
+ </dt>
+ <dd>
+ long numerical ISO data format version of this date.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:__eq"></a>
+ <strong>Date:__eq (other)</strong>
+ </dt>
+ <dd>
+ equality between Date objects.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">other</span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:__lt"></a>
+ <strong>Date:__lt (other)</strong>
+ </dt>
+ <dd>
+ ordering between Date objects.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">other</span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:__sub"></a>
+ <strong>Date:__sub ()</strong>
+ </dt>
+ <dd>
+ difference between Date objects.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date:__add"></a>
+ <strong>Date:__add (other)</strong>
+ </dt>
+ <dd>
+ add a date and an interval.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">other</span>
+ either a <a href="../classes/pl.Date.html#Date.Interval">Date.Interval</a> object or a table such as
+ passed to <a href="../classes/pl.Date.html#Date:add">Date:add</a>
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date.Interval"></a>
+ <strong>Date.Interval (t)</strong>
+ </dt>
+ <dd>
+ Date.Interval constructor
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">int</span></span>
+ an interval in seconds
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date.Interval:__tostring"></a>
+ <strong>Date.Interval:__tostring ()</strong>
+ </dt>
+ <dd>
+ If it&rsquo;s an interval then the format is &lsquo;2 hours 29 sec&rsquo; etc.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date.Format"></a>
+ <strong>Date.Format (fmt.)</strong>
+ </dt>
+ <dd>
+ Date.Format constructor.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fmt.</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A string where the following fields are significant:</p>
+
+<ul>
+<li> d day (either d or dd)</li>
+<li> y year (either yy or yyy)</li>
+<li> m month (either m or mm)</li>
+<li> H hour (either H or HH)</li>
+<li> M minute (either M or MM)</li>
+<li> S second (either S or SS)</li>
+</ul>
+
+
+<p> Alternatively, if fmt is nil then this returns a flexible date parser
+ that tries various date/time schemes in turn:</p>
+
+<ul>
+<li><a href="http://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a>, like <code>2010-05-10 12:35:23Z</code> or <code>2008-10-03T14:30+02</code></li>
+<li>times like 15:30 or 8.05pm (assumed to be today&rsquo;s date)</li>
+<li>dates like 28/10/02 (European order!) or 5 Feb 2012</li>
+<li>month name like march or Mar (case-insensitive, first 3 letters); here the
+day will be 1 and the year this current year</li>
+</ul>
+
+
+<p> A date in format 3 can be optionally followed by a time in format 2.
+ Please see test-date.lua in the tests folder for more examples.
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">df = Date.Format(<span class="string">"yyyy-mm-dd HH:MM:SS"</span>)</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "Date.Format:parse"></a>
+ <strong>Date.Format:parse (str)</strong>
+ </dt>
+ <dd>
+ parse a string into a Date object.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">str</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a date string
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ date object
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date.Format:tostring"></a>
+ <strong>Date.Format:tostring (d)</strong>
+ </dt>
+ <dd>
+ convert a Date object into a string.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">d</span>
+ a date object, or a time value as returned by <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.time">os.time</a>
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ string
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Date.Format:US_order"></a>
+ <strong>Date.Format:US_order (yesno)</strong>
+ </dt>
+ <dd>
+ force US order in dates like 9/11/2001
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">yesno</span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Methods"></a>Methods</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "pl.Date:Date"></a>
+ <strong>pl.Date:Date (t, ...)</strong>
+ </dt>
+ <dd>
+ Date constructor.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <p> this can be either</p>
+
+<ul>
+<li> <code>nil</code> or empty - use current date and time</li>
+<li> number - seconds since epoch (as returned by <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.time">os.time</a>). Resulting time is UTC</li>
+<li> <a href="../classes/pl.Date.html">Date</a> - make a copy of this date</li>
+<li> table - table containing year, month, etc as for <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.time">os.time</a>. You may leave out year, month or day,
+in which case current values will be used.</li>
+<li> year (will be followed by month, day etc)</li>
+</ul>
+
+ </li>
+ <li><span class="parameter">...</span>
+ true if Universal Coordinated Time, or two to five numbers: month,day,hour,min,sec
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/classes/pl.List.html b/docs/classes/pl.List.html
new file mode 100644
index 0000000..acc8e54
--- /dev/null
+++ b/docs/classes/pl.List.html
@@ -0,0 +1,1444 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+<li><a href="#metamethods">metamethods</a></li>
+</ul>
+
+
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><strong>pl.List</strong></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Class <code>pl.List</code></h1>
+<p>Python-style list class.</p>
+<p> <strong>Please Note</strong>: methods that change the list will return the list.
+ This is to allow for method chaining, but please note that <code>ls = ls:sort()</code>
+ does not mean that a new copy of the list is made. In-place (mutable) methods
+ are marked as returning &lsquo;the list&rsquo; in this documentation.</p>
+
+<p> See the Guide for further <a href="../manual/02-arrays.md.html#Python_style_Lists">discussion</a></p>
+
+<p> See <a href="http://www.python.org/doc/current/tut/tut.html">http://www.python.org/doc/current/tut/tut.html</a>, section 5.1</p>
+
+<p> <strong>Note</strong>: The comments before some of the functions are from the Python docs
+ and contain Python code.</p>
+
+<p> Written for Lua version Nick Trout 4.0; Redone for Lua 5.1, Steve Donovan.</p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.tablex.html#">pl.tablex</a>, <a href="../libraries/pl.class.html#">pl.class</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#List.new">List.new ([t])</a></td>
+ <td class="summary">Create a new list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:clone">List:clone ()</a></td>
+ <td class="summary">Make a copy of an existing list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:append">List:append (i)</a></td>
+ <td class="summary">Add an item to the end of the list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:extend">List:extend (L)</a></td>
+ <td class="summary">Extend the list by appending all the items in the given list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:insert">List:insert (i, x)</a></td>
+ <td class="summary">Insert an item at a given position.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:put">List:put (x)</a></td>
+ <td class="summary">Insert an item at the begining of the list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:remove">List:remove (i)</a></td>
+ <td class="summary">Remove an element given its index.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:remove_value">List:remove_value (x)</a></td>
+ <td class="summary">Remove the first item from the list whose value is given.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:pop">List:pop ([i])</a></td>
+ <td class="summary">Remove the item at the given position in the list, and return it.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:index">List:index (x[, idx=1])</a></td>
+ <td class="summary">Return the index in the list of the first item whose value is given.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:contains">List:contains (x)</a></td>
+ <td class="summary">Does this list contain the value?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:count">List:count (x)</a></td>
+ <td class="summary">Return the number of times value appears in the list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:sort">List:sort ([cmp='<'])</a></td>
+ <td class="summary">Sort the items of the list, in place.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:sorted">List:sorted ([cmp='<'])</a></td>
+ <td class="summary">Return a sorted copy of this list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:reverse">List:reverse ()</a></td>
+ <td class="summary">Reverse the elements of the list, in place.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:minmax">List:minmax ()</a></td>
+ <td class="summary">Return the minimum and the maximum value of the list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:slice">List:slice (first, last)</a></td>
+ <td class="summary">Emulate list slicing.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:clear">List:clear ()</a></td>
+ <td class="summary">Empty the list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List.range">List.range (start[, finish[, incr=1]])</a></td>
+ <td class="summary">Emulate Python&rsquo;s range(x) function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:len">List:len ()</a></td>
+ <td class="summary">list:len() is the same as #list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:chop">List:chop (i1, i2)</a></td>
+ <td class="summary">Remove a subrange of elements.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:splice">List:splice (idx, list)</a></td>
+ <td class="summary">Insert a sublist into a list
+ equivalent to &rsquo;s[idx:idx] = list' in Python</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:slice_assign">List:slice_assign (i1, i2, seq)</a></td>
+ <td class="summary">General slice assignment s[i1:i2] = seq.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:join">List:join ([delim=''])</a></td>
+ <td class="summary">Join the elements of a list using a delimiter.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:concat">List:concat ([delim=''])</a></td>
+ <td class="summary">Join a list of strings.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:foreach">List:foreach (fun, ...)</a></td>
+ <td class="summary">Call the function on each element of the list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:foreachm">List:foreachm (name, ...)</a></td>
+ <td class="summary">Call the named method on each element of the list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:filter">List:filter (fun[, arg])</a></td>
+ <td class="summary">Create a list of all elements which match a function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List.split">List.split (s[, delim])</a></td>
+ <td class="summary">Split a string using a delimiter.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:map">List:map (fun, ...)</a></td>
+ <td class="summary">Apply a function to all elements.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:transform">List:transform (fun, ...)</a></td>
+ <td class="summary">Apply a function to all elements, in-place.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:map2">List:map2 (fun, ls, ...)</a></td>
+ <td class="summary">Apply a function to elements of two lists.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:mapm">List:mapm (name, ...)</a></td>
+ <td class="summary">apply a named method to all elements.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:reduce">List:reduce (fun)</a></td>
+ <td class="summary">&lsquo;reduce&rsquo; a list using a binary function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:partition">List:partition (fun, ...)</a></td>
+ <td class="summary">Partition a list using a classifier function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:iter">List:iter ()</a></td>
+ <td class="summary">return an iterator over all values.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List.iterate">List.iterate (seq)</a></td>
+ <td class="summary">Create an iterator over a seqence.</td>
+ </tr>
+</table>
+<h2><a href="#metamethods">metamethods</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#List:__concat">List:__concat (L)</a></td>
+ <td class="summary">Concatenation operator.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:__eq">List:__eq (L)</a></td>
+ <td class="summary">Equality operator ==.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#List:__tostring">List:__tostring ()</a></td>
+ <td class="summary">How our list should be rendered as a string.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "List.new"></a>
+ <strong>List.new ([t])</strong>
+ </dt>
+ <dd>
+ Create a new list. Can optionally pass a table;
+ passing another instance of List will cause a copy to be created;
+ this will return a plain table with an appropriate metatable.
+ we pass anything which isn&rsquo;t a simple table to iterate() to work out
+ an appropriate iterator
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ An optional list-like table
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new List
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../classes/pl.List.html#List.iterate">List.iterate</a>
+ </ul>
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">ls = List(); ls = List {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "List:clone"></a>
+ <strong>List:clone ()</strong>
+ </dt>
+ <dd>
+ Make a copy of an existing list.
+ The difference from a plain &lsquo;copy constructor&rsquo; is that this returns
+ the actual List subtype.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:append"></a>
+ <strong>List:append (i)</strong>
+ </dt>
+ <dd>
+ Add an item to the end of the list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">i</span>
+ An item
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:extend"></a>
+ <strong>List:extend (L)</strong>
+ </dt>
+ <dd>
+ Extend the list by appending all the items in the given list.
+ equivalent to &lsquo;a[len(a):] = L&rsquo;.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">L</span>
+ <span class="types"><a class="type" href="../classes/pl.List.html">List</a></span>
+ Another List
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:insert"></a>
+ <strong>List:insert (i, x)</strong>
+ </dt>
+ <dd>
+ Insert an item at a given position. i is the index of the
+ element before which to insert.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">i</span>
+ <span class="types"><span class="type">int</span></span>
+ index of element before whichh to insert
+ </li>
+ <li><span class="parameter">x</span>
+ A data item
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:put"></a>
+ <strong>List:put (x)</strong>
+ </dt>
+ <dd>
+ Insert an item at the begining of the list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x</span>
+ a data item
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:remove"></a>
+ <strong>List:remove (i)</strong>
+ </dt>
+ <dd>
+ Remove an element given its index.
+ (equivalent of Python&rsquo;s del s[i])
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">i</span>
+ <span class="types"><span class="type">int</span></span>
+ the index
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:remove_value"></a>
+ <strong>List:remove_value (x)</strong>
+ </dt>
+ <dd>
+ Remove the first item from the list whose value is given.
+ (This is called &lsquo;remove&rsquo; in Python; renamed to avoid confusion
+ with table.remove)
+ Return nil if there is no such item.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x</span>
+ A data value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:pop"></a>
+ <strong>List:pop ([i])</strong>
+ </dt>
+ <dd>
+ Remove the item at the given position in the list, and return it.
+ If no index is specified, a:pop() returns the last item in the list.
+ The item is also removed from the list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">i</span>
+ <span class="types"><span class="type">int</span></span>
+ An index
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the item
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:index"></a>
+ <strong>List:index (x[, idx=1])</strong>
+ </dt>
+ <dd>
+ Return the index in the list of the first item whose value is given.
+ Return nil if there is no such item.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x</span>
+ A data value
+ </li>
+ <li><span class="parameter">idx</span>
+ <span class="types"><span class="type">int</span></span>
+ where to start search
+ (<em>default</em> 1)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the index, or nil if not found.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:contains"></a>
+ <strong>List:contains (x)</strong>
+ </dt>
+ <dd>
+ Does this list contain the value?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x</span>
+ A data value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or false
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:count"></a>
+ <strong>List:count (x)</strong>
+ </dt>
+ <dd>
+ Return the number of times value appears in the list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x</span>
+ A data value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ number of times x appears
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:sort"></a>
+ <strong>List:sort ([cmp='<'])</strong>
+ </dt>
+ <dd>
+ Sort the items of the list, in place.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">cmp</span>
+ <span class="types"><span class="type">func</span></span>
+ an optional comparison function
+ (<em>default</em> '<')
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:sorted"></a>
+ <strong>List:sorted ([cmp='<'])</strong>
+ </dt>
+ <dd>
+ Return a sorted copy of this list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">cmp</span>
+ <span class="types"><span class="type">func</span></span>
+ an optional comparison function
+ (<em>default</em> '<')
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:reverse"></a>
+ <strong>List:reverse ()</strong>
+ </dt>
+ <dd>
+ Reverse the elements of the list, in place.
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:minmax"></a>
+ <strong>List:minmax ()</strong>
+ </dt>
+ <dd>
+ Return the minimum and the maximum value of the list.
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ minimum value</li>
+ <li>
+ maximum value</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:slice"></a>
+ <strong>List:slice (first, last)</strong>
+ </dt>
+ <dd>
+ Emulate list slicing. like &lsquo;list[first:last]&rsquo; in Python.
+ If first or last are negative then they are relative to the end of the list
+ eg. slice(-2) gives last 2 entries in a list, and
+ slice(-4,-2) gives from -4th to -2nd
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">first</span>
+ An index
+ </li>
+ <li><span class="parameter">last</span>
+ An index
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new List
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:clear"></a>
+ <strong>List:clear ()</strong>
+ </dt>
+ <dd>
+ Empty the list.
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List.range"></a>
+ <strong>List.range (start[, finish[, incr=1]])</strong>
+ </dt>
+ <dd>
+ Emulate Python&rsquo;s range(x) function.
+ Include it in List table for tidiness
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">start</span>
+ <span class="types"><span class="type">int</span></span>
+ A number
+ </li>
+ <li><span class="parameter">finish</span>
+ <span class="types"><span class="type">int</span></span>
+ A number greater than start; if absent,
+ then start is 1 and finish is start
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">incr</span>
+ <span class="types"><span class="type">int</span></span>
+ an increment (may be less than 1)
+ (<em>default</em> 1)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a List from start .. finish
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">List.range(<span class="number">0</span>,<span class="number">3</span>) == List{<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}</pre></li>
+ <li><pre class="example">List.range(<span class="number">4</span>) = List{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>}</pre></li>
+ <li><pre class="example">List.range(<span class="number">5</span>,<span class="number">1</span>,-<span class="number">1</span>) == List{<span class="number">5</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">1</span>}</pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "List:len"></a>
+ <strong>List:len ()</strong>
+ </dt>
+ <dd>
+ list:len() is the same as #list.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:chop"></a>
+ <strong>List:chop (i1, i2)</strong>
+ </dt>
+ <dd>
+ Remove a subrange of elements.
+ equivalent to &lsquo;del s[i1:i2]&rsquo; in Python.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start of range
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end of range
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:splice"></a>
+ <strong>List:splice (idx, list)</strong>
+ </dt>
+ <dd>
+ Insert a sublist into a list
+ equivalent to &rsquo;s[idx:idx] = list' in Python
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">idx</span>
+ <span class="types"><span class="type">int</span></span>
+ index
+ </li>
+ <li><span class="parameter">list</span>
+ <span class="types"><a class="type" href="../classes/pl.List.html">List</a></span>
+ list to insert
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">l = List{<span class="number">10</span>,<span class="number">20</span>}; l:splice(<span class="number">2</span>,{<span class="number">21</span>,<span class="number">22</span>}); <span class="global">assert</span>(l == List{<span class="number">10</span>,<span class="number">21</span>,<span class="number">22</span>,<span class="number">20</span>})</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "List:slice_assign"></a>
+ <strong>List:slice_assign (i1, i2, seq)</strong>
+ </dt>
+ <dd>
+ General slice assignment s[i1:i2] = seq.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start index
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end index
+ </li>
+ <li><span class="parameter">seq</span>
+ <span class="types"><a class="type" href="../classes/pl.List.html">List</a></span>
+ a list
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:join"></a>
+ <strong>List:join ([delim=''])</strong>
+ </dt>
+ <dd>
+ Join the elements of a list using a delimiter.
+ This method uses tostring on all elements.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">delim</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a delimiter string, can be empty.
+ (<em>default</em> '')
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:concat"></a>
+ <strong>List:concat ([delim=''])</strong>
+ </dt>
+ <dd>
+ Join a list of strings. <br>
+ Uses <a href="https://www.lua.org/manual/5.1/manual.html#pdf-table.concat">table.concat</a> directly.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">delim</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a delimiter
+ (<em>default</em> '')
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:foreach"></a>
+ <strong>List:foreach (fun, ...)</strong>
+ </dt>
+ <dd>
+ Call the function on each element of the list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function or callable object
+ </li>
+ <li><span class="parameter">...</span>
+ optional values to pass to function
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:foreachm"></a>
+ <strong>List:foreachm (name, ...)</strong>
+ </dt>
+ <dd>
+ Call the named method on each element of the list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">name</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the method name
+ </li>
+ <li><span class="parameter">...</span>
+ optional values to pass to function
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:filter"></a>
+ <strong>List:filter (fun[, arg])</strong>
+ </dt>
+ <dd>
+ Create a list of all elements which match a function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a boolean function
+ </li>
+ <li><span class="parameter">arg</span>
+ optional argument to be passed as second argument of the predicate
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new filtered list.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List.split"></a>
+ <strong>List.split (s[, delim])</strong>
+ </dt>
+ <dd>
+ Split a string using a delimiter.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">delim</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the delimiter (default spaces)
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a List of strings
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.utils.html#split">pl.utils.split</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "List:map"></a>
+ <strong>List:map (fun, ...)</strong>
+ </dt>
+ <dd>
+ Apply a function to all elements.
+ Any extra arguments will be passed to the function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least one argument
+ </li>
+ <li><span class="parameter">...</span>
+ arbitrary extra arguments.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new list: {f(x) for x in self}
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#imap">pl.tablex.imap</a>
+ </ul>
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">List{<span class="string">'one'</span>,<span class="string">'two'</span>}:map(<span class="global">string</span>.upper) == {<span class="string">'ONE'</span>,<span class="string">'TWO'</span>}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "List:transform"></a>
+ <strong>List:transform (fun, ...)</strong>
+ </dt>
+ <dd>
+ Apply a function to all elements, in-place.
+ Any extra arguments are passed to the function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ A function that takes at least one argument
+ </li>
+ <li><span class="parameter">...</span>
+ arbitrary extra arguments.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the list.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:map2"></a>
+ <strong>List:map2 (fun, ls, ...)</strong>
+ </dt>
+ <dd>
+ Apply a function to elements of two lists.
+ Any extra arguments will be passed to the function
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least two arguments
+ </li>
+ <li><span class="parameter">ls</span>
+ <span class="types"><a class="type" href="../classes/pl.List.html">List</a></span>
+ another list
+ </li>
+ <li><span class="parameter">...</span>
+ arbitrary extra arguments.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new list: {f(x,y) for x in self, for x in arg1}
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#imap2">pl.tablex.imap2</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "List:mapm"></a>
+ <strong>List:mapm (name, ...)</strong>
+ </dt>
+ <dd>
+ apply a named method to all elements.
+ Any extra arguments will be passed to the method.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">name</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ name of method
+ </li>
+ <li><span class="parameter">...</span>
+ extra arguments
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new list of the results
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.seq.html#mapmethod">pl.seq.mapmethod</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "List:reduce"></a>
+ <strong>List:reduce (fun)</strong>
+ </dt>
+ <dd>
+ &lsquo;reduce&rsquo; a list using a binary function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of two arguments
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ result of the function
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#reduce">pl.tablex.reduce</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "List:partition"></a>
+ <strong>List:partition (fun, ...)</strong>
+ </dt>
+ <dd>
+ Partition a list using a classifier function.
+ The function may return nil, but this will be converted to the string key &lsquo;<nil>&rsquo;.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least one argument
+ </li>
+ <li><span class="parameter">...</span>
+ will also be passed to the function
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="../classes/pl.MultiMap.html">MultiMap</a></span>
+ a table where the keys are the returned values, and the values are Lists
+ of values where the function returned that key.
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../classes/pl.MultiMap.html#">pl.MultiMap</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "List:iter"></a>
+ <strong>List:iter ()</strong>
+ </dt>
+ <dd>
+ return an iterator over all values.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List.iterate"></a>
+ <strong>List.iterate (seq)</strong>
+ </dt>
+ <dd>
+ Create an iterator over a seqence.
+ This captures the Python concept of &lsquo;sequence&rsquo;.
+ For tables, iterates over all values with integer indices.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">seq</span>
+ a sequence; a string (over characters), a table, a file object (over lines) or an iterator function
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example"><span class="keyword">for</span> x <span class="keyword">in</span> iterate {<span class="number">1</span>,<span class="number">10</span>,<span class="number">22</span>,<span class="number">55</span>} <span class="keyword">do</span> <span class="global">io</span>.write(x,<span class="string">','</span>) <span class="keyword">end</span> ==&gt; <span class="number">1</span>,<span class="number">10</span>,<span class="number">22</span>,<span class="number">55</span></pre></li>
+ <li><pre class="example"><span class="keyword">for</span> ch <span class="keyword">in</span> iterate <span class="string">'help'</span> <span class="keyword">do</span> <span class="keyword">do</span> <span class="global">io</span>.write(ch,<span class="string">' '</span>) <span class="keyword">end</span> ==&gt; h e l p</pre></li>
+ </ul>
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="metamethods"></a>metamethods</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "List:__concat"></a>
+ <strong>List:__concat (L)</strong>
+ </dt>
+ <dd>
+ Concatenation operator.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">L</span>
+ <span class="types"><a class="type" href="../classes/pl.List.html">List</a></span>
+ another List
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new list consisting of the list with the elements of the new list appended
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:__eq"></a>
+ <strong>List:__eq (L)</strong>
+ </dt>
+ <dd>
+ Equality operator ==. True iff all elements of two lists are equal.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">L</span>
+ <span class="types"><a class="type" href="../classes/pl.List.html">List</a></span>
+ another List
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or false
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "List:__tostring"></a>
+ <strong>List:__tostring ()</strong>
+ </dt>
+ <dd>
+ How our list should be rendered as a string. Uses join().
+
+
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../classes/pl.List.html#List:join">List:join</a>
+ </ul>
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/classes/pl.Map.html b/docs/classes/pl.Map.html
new file mode 100644
index 0000000..98becae
--- /dev/null
+++ b/docs/classes/pl.Map.html
@@ -0,0 +1,419 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Fields">Fields</a></li>
+<li><a href="#Methods">Methods</a></li>
+<li><a href="#Metamethods">Metamethods</a></li>
+</ul>
+
+
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><strong>pl.Map</strong></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Class <code>pl.Map</code></h1>
+<p>A Map class.</p>
+<p>
+
+<pre>
+&gt; Map = <span class="global">require</span> <span class="string">'pl.Map'</span>
+&gt; m = Map{one=<span class="number">1</span>,two=<span class="number">2</span>}
+&gt; m:update {three=<span class="number">3</span>,four=<span class="number">4</span>,two=<span class="number">20</span>}
+&gt; = m == M{one=<span class="number">1</span>,two=<span class="number">20</span>,three=<span class="number">3</span>,four=<span class="number">4</span>}
+<span class="keyword">true</span>
+</pre>
+
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.class.html#">pl.class</a>, <a href="../libraries/pl.tablex.html#">pl.tablex</a>, <a href="../libraries/pl.pretty.html#">pl.pretty</a></p></p>
+
+
+<h2><a href="#Fields">Fields</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map.keys">pl.Map.keys</a></td>
+ <td class="summary">list of keys.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map.values">pl.Map.values</a></td>
+ <td class="summary">list of values.</td>
+ </tr>
+</table>
+<h2><a href="#Methods">Methods</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:iter">pl.Map:iter ()</a></td>
+ <td class="summary">return an iterator over all key-value pairs.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:items">pl.Map:items ()</a></td>
+ <td class="summary">return a List of all key-value pairs, sorted by the keys.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:len">pl.Map:len ()</a></td>
+ <td class="summary">size of map.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:set">pl.Map:set (key, val)</a></td>
+ <td class="summary">put a value into the map.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:get">pl.Map:get (key)</a></td>
+ <td class="summary">get a value from the map.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:getvalues">pl.Map:getvalues (keys)</a></td>
+ <td class="summary">get a list of values indexed by a list of keys.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:update">pl.Map:update (table)</a></td>
+ <td class="summary">update the map using key/value pairs from another table.</td>
+ </tr>
+</table>
+<h2><a href="#Metamethods">Metamethods</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:__eq">pl.Map:__eq (m)</a></td>
+ <td class="summary">equality between maps.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.Map:__tostring">pl.Map:__tostring ()</a></td>
+ <td class="summary">string representation of a map.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Fields"></a>Fields</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "pl.Map.keys"></a>
+ <strong>pl.Map.keys</strong>
+ </dt>
+ <dd>
+ list of keys.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.Map.values"></a>
+ <strong>pl.Map.values</strong>
+ </dt>
+ <dd>
+ list of values.
+
+
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Methods"></a>Methods</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "pl.Map:iter"></a>
+ <strong>pl.Map:iter ()</strong>
+ </dt>
+ <dd>
+ return an iterator over all key-value pairs.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.Map:items"></a>
+ <strong>pl.Map:items ()</strong>
+ </dt>
+ <dd>
+ return a List of all key-value pairs, sorted by the keys.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.Map:len"></a>
+ <strong>pl.Map:len ()</strong>
+ </dt>
+ <dd>
+ size of map.
+ note: this is a relatively expensive operation!
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.Map:set"></a>
+ <strong>pl.Map:set (key, val)</strong>
+ </dt>
+ <dd>
+ put a value into the map.
+ This will remove the key if the value is <code>nil</code>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">key</span>
+ the key
+ </li>
+ <li><span class="parameter">val</span>
+ the value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.Map:get"></a>
+ <strong>pl.Map:get (key)</strong>
+ </dt>
+ <dd>
+ get a value from the map.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">key</span>
+ the key
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the value, or nil if not found.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.Map:getvalues"></a>
+ <strong>pl.Map:getvalues (keys)</strong>
+ </dt>
+ <dd>
+ get a list of values indexed by a list of keys.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">keys</span>
+ a list-like table of keys
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.Map:update"></a>
+ <strong>pl.Map:update (table)</strong>
+ </dt>
+ <dd>
+ update the map using key/value pairs from another table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">table</span>
+ <span class="types"><span class="type">tab</span></span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Metamethods"></a>Metamethods</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "pl.Map:__eq"></a>
+ <strong>pl.Map:__eq (m)</strong>
+ </dt>
+ <dd>
+ equality between maps.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">m</span>
+ <span class="types"><a class="type" href="../classes/pl.Map.html">Map</a></span>
+ another map.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.Map:__tostring"></a>
+ <strong>pl.Map:__tostring ()</strong>
+ </dt>
+ <dd>
+ string representation of a map.
+
+
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/classes/pl.MultiMap.html b/docs/classes/pl.MultiMap.html
new file mode 100644
index 0000000..21835cf
--- /dev/null
+++ b/docs/classes/pl.MultiMap.html
@@ -0,0 +1,208 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Methods">Methods</a></li>
+</ul>
+
+
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><strong>pl.MultiMap</strong></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Class <code>pl.MultiMap</code></h1>
+<p>MultiMap, a Map which has multiple values per key.</p>
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.class.html#">pl.class</a>, <a href="../classes/pl.List.html#">pl.List</a>, <a href="../classes/pl.Map.html#">pl.Map</a></p>
+
+
+<h2><a href="#Methods">Methods</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#pl.MultiMap:update">pl.MultiMap:update (t)</a></td>
+ <td class="summary">update a MultiMap using a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.MultiMap:set">pl.MultiMap:set (key, val)</a></td>
+ <td class="summary">add a new value to a key.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Methods"></a>Methods</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "pl.MultiMap:update"></a>
+ <strong>pl.MultiMap:update (t)</strong>
+ </dt>
+ <dd>
+ update a MultiMap using a table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ either a Multimap or a map-like table.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the map
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.MultiMap:set"></a>
+ <strong>pl.MultiMap:set (key, val)</strong>
+ </dt>
+ <dd>
+ add a new value to a key. Setting a nil value removes the key.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">key</span>
+ the key
+ </li>
+ <li><span class="parameter">val</span>
+ the value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the map
+ </ol>
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/classes/pl.OrderedMap.html b/docs/classes/pl.OrderedMap.html
new file mode 100644
index 0000000..6f26905
--- /dev/null
+++ b/docs/classes/pl.OrderedMap.html
@@ -0,0 +1,418 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Methods">Methods</a></li>
+<li><a href="#Metamethods">Metamethods</a></li>
+</ul>
+
+
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><strong>pl.OrderedMap</strong></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Class <code>pl.OrderedMap</code></h1>
+<p>OrderedMap, a map which preserves ordering.</p>
+<p> Derived from <a href="../classes/pl.Map.html#">pl.Map</a>.</p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.tablex.html#">pl.tablex</a>, <a href="../libraries/pl.class.html#">pl.class</a>, <a href="../classes/pl.List.html#">pl.List</a>, <a href="../classes/pl.Map.html#">pl.Map</a></p>
+
+
+<h2><a href="#Methods">Methods</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:_init">pl.OrderedMap:_init (t)</a></td>
+ <td class="summary">construct an OrderedMap.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:update">pl.OrderedMap:update (t)</a></td>
+ <td class="summary">update an OrderedMap using a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:set">pl.OrderedMap:set (key, val)</a></td>
+ <td class="summary">set the key&rsquo;s value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:insert">pl.OrderedMap:insert (pos, key, val)</a></td>
+ <td class="summary">insert a key/value pair before a given position.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:keys">pl.OrderedMap:keys ()</a></td>
+ <td class="summary">return the keys in order.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:values">pl.OrderedMap:values ()</a></td>
+ <td class="summary">return the values in order.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:sort">pl.OrderedMap:sort (cmp)</a></td>
+ <td class="summary">sort the keys.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:iter">pl.OrderedMap:iter ()</a></td>
+ <td class="summary">iterate over key-value pairs in order.</td>
+ </tr>
+</table>
+<h2><a href="#Metamethods">Metamethods</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:__pairs">pl.OrderedMap:__pairs ()</a></td>
+ <td class="summary">iterate over an ordered map (5.2).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pl.OrderedMap:__tostring">pl.OrderedMap:__tostring ()</a></td>
+ <td class="summary">string representation of an ordered map.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Methods"></a>Methods</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "pl.OrderedMap:_init"></a>
+ <strong>pl.OrderedMap:_init (t)</strong>
+ </dt>
+ <dd>
+ construct an OrderedMap.
+ Will throw an error if the argument is bad.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ optional initialization table, same as for <a href="../classes/pl.OrderedMap.html#pl.OrderedMap:update">OrderedMap:update</a>
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.OrderedMap:update"></a>
+ <strong>pl.OrderedMap:update (t)</strong>
+ </dt>
+ <dd>
+ update an OrderedMap using a table.
+ If the table is itself an OrderedMap, then its entries will be appended.
+ if it s a table of the form <code>{{key1=val1},{key2=val2},&hellip;}</code> these will be appended.</p>
+
+<p> Otherwise, it is assumed to be a map-like table, and order of extra entries is arbitrary.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ the map, or nil in case of error</li>
+ <li>
+ the error message</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.OrderedMap:set"></a>
+ <strong>pl.OrderedMap:set (key, val)</strong>
+ </dt>
+ <dd>
+ set the key&rsquo;s value. This key will be appended at the end of the map.</p>
+
+<p> If the value is nil, then the key is removed.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">key</span>
+ the key
+ </li>
+ <li><span class="parameter">val</span>
+ the value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the map
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.OrderedMap:insert"></a>
+ <strong>pl.OrderedMap:insert (pos, key, val)</strong>
+ </dt>
+ <dd>
+ insert a key/value pair before a given position.
+ Note: if the map already contains the key, then this effectively
+ moves the item to the new position by first removing at the old position.
+ Has no effect if the key does not exist and val is nil
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">pos</span>
+ <span class="types"><span class="type">int</span></span>
+ a position starting at 1
+ </li>
+ <li><span class="parameter">key</span>
+ the key
+ </li>
+ <li><span class="parameter">val</span>
+ the value; if nil use the old value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.OrderedMap:keys"></a>
+ <strong>pl.OrderedMap:keys ()</strong>
+ </dt>
+ <dd>
+ return the keys in order.
+ (Not a copy!)
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ List
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.OrderedMap:values"></a>
+ <strong>pl.OrderedMap:values ()</strong>
+ </dt>
+ <dd>
+ return the values in order.
+ this is relatively expensive.
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ List
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.OrderedMap:sort"></a>
+ <strong>pl.OrderedMap:sort (cmp)</strong>
+ </dt>
+ <dd>
+ sort the keys.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">cmp</span>
+ <span class="types"><span class="type">func</span></span>
+ a comparison function as for <a href="https://www.lua.org/manual/5.1/manual.html#pdf-table.sort">table.sort</a>
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the map
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.OrderedMap:iter"></a>
+ <strong>pl.OrderedMap:iter ()</strong>
+ </dt>
+ <dd>
+ iterate over key-value pairs in order.
+
+
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Metamethods"></a>Metamethods</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "pl.OrderedMap:__pairs"></a>
+ <strong>pl.OrderedMap:__pairs ()</strong>
+ </dt>
+ <dd>
+ iterate over an ordered map (5.2).
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pl.OrderedMap:__tostring"></a>
+ <strong>pl.OrderedMap:__tostring ()</strong>
+ </dt>
+ <dd>
+ string representation of an ordered map.
+
+
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/seesubst.lua.html b/docs/examples/seesubst.lua.html
new file mode 100644
index 0000000..3ff98aa
--- /dev/null
+++ b/docs/examples/seesubst.lua.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><strong>seesubst.lua</strong></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>seesubst.lua</h2>
+<pre>
+<span class="comment">-- shows how replacing '@see module' in the Markdown documentation
+</span><span class="comment">-- can be done more elegantly using PL.
+</span><span class="comment">-- We either have something like 'pl.config' (a module reference)
+</span><span class="comment">-- or 'pl.seq.map' (a function reference); these cases must be distinguished
+</span><span class="comment">-- and a Markdown link generated pointing to the LuaDoc file.
+</span>
+<span class="keyword">local</span> sip = <span class="global">require</span> <span class="string">'pl.sip'</span>
+<span class="keyword">local</span> stringx = <span class="global">require</span> <span class="string">'pl.stringx'</span>
+
+<span class="keyword">local</span> res = {}
+<span class="keyword">local</span> s = <span class="string">[[
+(@see pl.bonzo.dog)
+remember about @see pl.bonzo
+
+]]</span>
+
+<span class="keyword">local</span> _gsub_patterns = {}
+
+<span class="keyword">local</span> <span class="keyword">function</span> gsub (s,pat,subst,start)
+ <span class="keyword">local</span> fpat = _gsub_patterns[pat]
+ <span class="keyword">if</span> <span class="keyword">not</span> fpat <span class="keyword">then</span>
+ <span class="comment">-- use SIP to generate a proper string pattern.
+</span> <span class="comment">-- the _whole thing_ is a capture, to get the whole match
+</span> <span class="comment">-- and the unnamed capture.
+</span> fpat = <span class="string">'('</span>..sip.create_pattern(pat)..<span class="string">')'</span>
+ _gsub_patterns[pat] = fpat
+ <span class="keyword">end</span>
+ <span class="keyword">return</span> s:gsub(fpat,subst,start)
+<span class="keyword">end</span>
+
+
+<span class="keyword">local</span> mod = sip.compile <span class="string">'$v.$v'</span>
+<span class="keyword">local</span> fun = sip.compile <span class="string">'$v.$v.$v'</span>
+
+<span class="keyword">for</span> line <span class="keyword">in</span> stringx.lines(s) <span class="keyword">do</span>
+ line = gsub(line,<span class="string">'@see $p'</span>,<span class="keyword">function</span>(see,path)
+ <span class="keyword">if</span> fun(path,res) <span class="keyword">or</span> mod(path,res) <span class="keyword">then</span>
+ <span class="keyword">local</span> ret = (<span class="string">'[see %s](%s.%s.html'</span>):format(path,res[<span class="number">1</span>],res[<span class="number">2</span>])
+ <span class="keyword">if</span> res[<span class="number">3</span>] <span class="keyword">then</span>
+ <span class="keyword">return</span> ret..<span class="string">'#'</span>..res[<span class="number">3</span>]..<span class="string">')'</span>
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> ret..<span class="string">')'</span>
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>)
+ <span class="global">print</span>(line)
+<span class="keyword">end</span></pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/sipscan.lua.html b/docs/examples/sipscan.lua.html
new file mode 100644
index 0000000..55c7279
--- /dev/null
+++ b/docs/examples/sipscan.lua.html
@@ -0,0 +1,162 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><strong>sipscan.lua</strong></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>sipscan.lua</h2>
+<pre>
+<span class="comment">-- another SIP example, shows how an awkward log file format
+</span><span class="comment">-- can be parsed. It also prints out the actual Lua string
+</span><span class="comment">-- pattern generated:
+</span><span class="comment">-- SYNC%s*%[([+%-%d]%d*)%]%s*([+%-%d]%d*)%s*([+%-%d]%d*)
+</span>
+<span class="keyword">local</span> sip = <span class="global">require</span> <span class="string">'pl.sip'</span>
+<span class="keyword">local</span> stringx = <span class="global">require</span> <span class="string">'pl.stringx'</span>
+
+<span class="keyword">local</span> s = <span class="string">[[
+SYNC [1] 0 547 (14679 sec)
+SYNC [2] 0 555 (14679 sec)
+SYNC [3] 0 563 (14679 sec)
+SYNC [4] 0 571 (14679 sec)
+SYNC [5] -1 580 (14679 sec)
+SYNC [6] 0 587 (14679 sec)
+]]</span>
+
+
+<span class="keyword">local</span> first = <span class="keyword">true</span>
+<span class="keyword">local</span> expected
+<span class="keyword">local</span> res = {}
+<span class="keyword">local</span> pat = <span class="string">'SYNC [$i{seq}] $i{diff} $i{val}'</span>
+<span class="global">print</span>(sip.create_pattern(pat))
+<span class="keyword">local</span> match = sip.compile(pat)
+<span class="keyword">for</span> line <span class="keyword">in</span> stringx.lines(s) <span class="keyword">do</span>
+ <span class="keyword">if</span> match(line,res) <span class="keyword">then</span>
+ <span class="keyword">if</span> first <span class="keyword">then</span>
+ expected = res.val
+ first = <span class="keyword">false</span>
+ <span class="keyword">end</span>
+ <span class="global">print</span>(res.val,expected - res.val)
+ expected = expected + <span class="number">8</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span></pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/symbols.lua.html b/docs/examples/symbols.lua.html
new file mode 100644
index 0000000..aa6b7b3
--- /dev/null
+++ b/docs/examples/symbols.lua.html
@@ -0,0 +1,348 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><strong>symbols.lua</strong></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>symbols.lua</h2>
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+utils.import <span class="string">'pl.func'</span>
+<span class="keyword">local</span> ops = <span class="global">require</span> <span class="string">'pl.operator'</span>
+<span class="keyword">local</span> List = <span class="global">require</span> <span class="string">'pl.List'</span>
+<span class="keyword">local</span> append,concat = <span class="global">table</span>.insert,<span class="global">table</span>.concat
+<span class="keyword">local</span> compare,find_if,compare_no_order,imap,reduce,count_map = tablex.compare,tablex.find_if,tablex.compare_no_order,tablex.imap,tablex.reduce,tablex.count_map
+<span class="keyword">local</span> <span class="global">unpack</span> = <span class="global">table</span>.<span class="global">unpack</span>
+
+<span class="keyword">function</span> bindval (self,val)
+ <span class="global">rawset</span>(self,<span class="string">'value'</span>,val)
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> optable = ops.optable
+
+<span class="keyword">function</span> sexpr (e)
+ <span class="keyword">if</span> isPE(e) <span class="keyword">then</span>
+ <span class="keyword">if</span> e.op ~= <span class="string">'X'</span> <span class="keyword">then</span>
+ <span class="keyword">local</span> args = tablex.imap(sexpr,e)
+ <span class="keyword">return</span> <span class="string">'('</span>..e.op..<span class="string">' '</span>..<span class="global">table</span>.concat(args,<span class="string">' '</span>)..<span class="string">')'</span>
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> e.repr
+ <span class="keyword">end</span>
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> <span class="global">tostring</span>(e)
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+
+psexpr = compose(<span class="global">print</span>,sexpr)
+
+
+
+<span class="keyword">function</span> equals (e1,e2)
+ <span class="keyword">local</span> p1,p2 = isPE(e1),isPE(e2)
+ <span class="keyword">if</span> p1 ~= p2 <span class="keyword">then</span> <span class="keyword">return</span> <span class="keyword">false</span> <span class="keyword">end</span> <span class="comment">-- different kinds of animals!
+</span> <span class="keyword">if</span> p1 <span class="keyword">and</span> p2 <span class="keyword">then</span> <span class="comment">-- both PEs
+</span> <span class="comment">-- operators must be the same
+</span> <span class="keyword">if</span> e1.op ~= e2.op <span class="keyword">then</span> <span class="keyword">return</span> <span class="keyword">false</span> <span class="keyword">end</span>
+ <span class="comment">-- PHs are equal if their representations are equal
+</span> <span class="keyword">if</span> e1.op == <span class="string">'X'</span> <span class="keyword">then</span> <span class="keyword">return</span> e1.repr == e2.repr
+ <span class="comment">-- commutative operators
+</span> <span class="keyword">elseif</span> e1.op == <span class="string">'+'</span> <span class="keyword">or</span> e1.op == <span class="string">'*'</span> <span class="keyword">then</span>
+ <span class="keyword">return</span> compare_no_order(e1,e2,equals)
+ <span class="keyword">else</span>
+ <span class="comment">-- arguments must be the same
+</span> <span class="keyword">return</span> compare(e1,e2,equals)
+ <span class="keyword">end</span>
+ <span class="keyword">else</span> <span class="comment">-- fall back on simple equality for non PEs
+</span> <span class="keyword">return</span> e1 == e2
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="comment">-- run down an unbalanced operator chain (like a+b+c) and return the arguments {a,b,c}
+</span><span class="keyword">function</span> tcollect (op,e,ls)
+ <span class="keyword">if</span> isPE(e) <span class="keyword">and</span> e.op == op <span class="keyword">then</span>
+ <span class="keyword">for</span> i = <span class="number">1</span>,#e <span class="keyword">do</span>
+ tcollect(op,e[i],ls)
+ <span class="keyword">end</span>
+ <span class="keyword">else</span>
+ ls:append(e)
+ <span class="keyword">return</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="keyword">function</span> rcollect (e)
+ <span class="keyword">local</span> res = List()
+ tcollect(e.op,e,res)
+ <span class="keyword">return</span> res
+<span class="keyword">end</span>
+
+
+<span class="comment">-- balance ensures that +/* chains are collected together, operates in-place.
+</span><span class="comment">-- thus (+(+ a b) c) or (+ a (+ b c)) becomes (+ a b c), order immaterial
+</span><span class="keyword">function</span> balance (e)
+ <span class="keyword">if</span> isPE(e) <span class="keyword">and</span> e.op ~= <span class="string">'X'</span> <span class="keyword">then</span>
+ <span class="keyword">local</span> op,args = e.op
+ <span class="keyword">if</span> op == <span class="string">'+'</span> <span class="keyword">or</span> op == <span class="string">'*'</span> <span class="keyword">then</span>
+ args = rcollect(e)
+ <span class="keyword">else</span>
+ args = imap(balance,e)
+ <span class="keyword">end</span>
+ <span class="keyword">for</span> i = <span class="number">1</span>,#args <span class="keyword">do</span>
+ e[i] = args[i]
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">return</span> e
+<span class="keyword">end</span>
+
+<span class="comment">-- fold constants in an expression
+</span><span class="keyword">function</span> fold (e)
+ <span class="keyword">if</span> isPE(e) <span class="keyword">then</span>
+ <span class="keyword">if</span> e.op == <span class="string">'X'</span> <span class="keyword">then</span>
+ <span class="comment">-- there could be _bound values_!
+</span> <span class="keyword">local</span> val = <span class="global">rawget</span>(e,<span class="string">'value'</span>)
+ <span class="keyword">return</span> val <span class="keyword">and</span> val <span class="keyword">or</span> e
+ <span class="keyword">else</span>
+ <span class="keyword">local</span> op = e.op
+ <span class="keyword">local</span> addmul = op == <span class="string">'*'</span> <span class="keyword">or</span> op == <span class="string">'+'</span>
+ <span class="comment">-- first fold all arguments
+</span> <span class="keyword">local</span> args = imap(fold,e)
+ <span class="keyword">if</span> <span class="keyword">not</span> addmul <span class="keyword">and</span> <span class="keyword">not</span> find_if(args,isPE) <span class="keyword">then</span>
+ <span class="comment">-- no placeholders in these args, we can fold the expression.
+</span> <span class="keyword">local</span> opfn = optable[op]
+ <span class="keyword">if</span> opfn <span class="keyword">then</span>
+ <span class="keyword">return</span> opfn(<span class="global">unpack</span>(args))
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> <span class="string">'?'</span>
+ <span class="keyword">end</span>
+ <span class="keyword">elseif</span> addmul <span class="keyword">then</span>
+ <span class="comment">-- enforce a few rules for + and *
+</span> <span class="comment">-- split the args into two classes, PE args and non-PE args.
+</span> <span class="keyword">local</span> classes = List.partition(args,isPE)
+ <span class="keyword">local</span> pe,npe = classes[<span class="keyword">true</span>],classes[<span class="keyword">false</span>]
+ <span class="keyword">if</span> npe <span class="keyword">then</span> <span class="comment">-- there's at least one non PE argument
+</span> <span class="comment">-- so fold them
+</span> <span class="keyword">if</span> #npe == <span class="number">1</span> <span class="keyword">then</span> npe = npe[<span class="number">1</span>]
+ <span class="keyword">else</span> npe = npe:reduce(optable[op])
+ <span class="keyword">end</span>
+ <span class="comment">-- if the result is a constant, return it
+</span> <span class="keyword">if</span> <span class="keyword">not</span> pe <span class="keyword">then</span> <span class="keyword">return</span> npe <span class="keyword">end</span>
+
+ <span class="comment">-- either (* 1 x) =&gt; x or (* 1 x y ...) =&gt; (* x y ...)
+</span> <span class="keyword">if</span> op == <span class="string">'*'</span> <span class="keyword">then</span>
+ <span class="keyword">if</span> npe == <span class="number">0</span> <span class="keyword">then</span> <span class="keyword">return</span> <span class="number">0</span>
+ <span class="keyword">elseif</span> npe == <span class="number">1</span> <span class="keyword">then</span> <span class="comment">-- identity
+</span> <span class="keyword">if</span> #pe == <span class="number">1</span> <span class="keyword">then</span> <span class="keyword">return</span> pe[<span class="number">1</span>] <span class="keyword">else</span> npe = <span class="keyword">nil</span> <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">else</span> <span class="comment">-- special cases for +
+</span> <span class="keyword">if</span> npe == <span class="number">0</span> <span class="keyword">then</span> <span class="comment">-- identity
+</span> <span class="keyword">if</span> #pe == <span class="number">1</span> <span class="keyword">then</span> <span class="keyword">return</span> pe[<span class="number">1</span>] <span class="keyword">else</span> npe = <span class="keyword">nil</span> <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="comment">-- build up the final arguments
+</span> <span class="keyword">local</span> res = {}
+ <span class="keyword">if</span> npe <span class="keyword">then</span> append(res,npe) <span class="keyword">end</span>
+ <span class="keyword">for</span> val,count <span class="keyword">in</span> <span class="global">pairs</span>(count_map(pe,equals)) <span class="keyword">do</span>
+ <span class="keyword">if</span> count &gt; <span class="number">1</span> <span class="keyword">then</span>
+ <span class="keyword">if</span> op == <span class="string">'*'</span> <span class="keyword">then</span> val = val ^ count
+ <span class="keyword">else</span> val = val * count
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ append(res,val)
+ <span class="keyword">end</span>
+ <span class="keyword">if</span> #res == <span class="number">1</span> <span class="keyword">then</span> <span class="keyword">return</span> res[<span class="number">1</span>] <span class="keyword">end</span>
+ <span class="keyword">return</span> PE{op=op,<span class="global">unpack</span>(res)}
+ <span class="keyword">elseif</span> op == <span class="string">'^'</span> <span class="keyword">then</span>
+ <span class="keyword">if</span> args[<span class="number">2</span>] == <span class="number">1</span> <span class="keyword">then</span> <span class="keyword">return</span> args[<span class="number">1</span>] <span class="keyword">end</span> <span class="comment">-- identity
+</span> <span class="keyword">if</span> args[<span class="number">2</span>] == <span class="number">0</span> <span class="keyword">then</span> <span class="keyword">return</span> <span class="number">1</span> <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">return</span> PE{op=op,<span class="global">unpack</span>(args)}
+ <span class="keyword">end</span>
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> e
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="keyword">function</span> expand (e)
+ <span class="keyword">if</span> isPE(e) <span class="keyword">and</span> e.op == <span class="string">'*'</span> <span class="keyword">and</span> isPE(e[<span class="number">2</span>]) <span class="keyword">and</span> e[<span class="number">2</span>].op == <span class="string">'+'</span> <span class="keyword">then</span>
+ <span class="keyword">local</span> a,b = e[<span class="number">1</span>],e[<span class="number">2</span>]
+ <span class="keyword">return</span> expand(b[<span class="number">1</span>]*a) + expand(b[<span class="number">2</span>]*a)
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> e
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="keyword">function</span> isnumber (x)
+ <span class="keyword">return</span> <span class="global">type</span>(x) == <span class="string">'number'</span>
+<span class="keyword">end</span>
+
+<span class="comment">-- does this PE contain a reference to x?
+</span><span class="keyword">function</span> references (e,x)
+ <span class="keyword">if</span> isPE(e) <span class="keyword">then</span>
+ <span class="keyword">if</span> e.op == <span class="string">'X'</span> <span class="keyword">then</span> <span class="keyword">return</span> x.repr == e.repr
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> find_if(e,references,x)
+ <span class="keyword">end</span>
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> <span class="keyword">false</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> <span class="keyword">function</span> muli (args)
+ <span class="keyword">return</span> PE{op=<span class="string">'*'</span>,<span class="global">unpack</span>(args)}
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> <span class="keyword">function</span> addi (args)
+ <span class="keyword">return</span> PE{op=<span class="string">'+'</span>,<span class="global">unpack</span>(args)}
+<span class="keyword">end</span>
+
+<span class="keyword">function</span> diff (e,x)
+ <span class="keyword">if</span> isPE(e) <span class="keyword">and</span> references(e,x) <span class="keyword">then</span>
+ <span class="keyword">local</span> op = e.op
+ <span class="keyword">if</span> op == <span class="string">'X'</span> <span class="keyword">then</span>
+ <span class="keyword">return</span> <span class="number">1</span>
+ <span class="keyword">else</span>
+ <span class="keyword">local</span> a,b = e[<span class="number">1</span>],e[<span class="number">2</span>]
+ <span class="keyword">if</span> op == <span class="string">'+'</span> <span class="keyword">then</span> <span class="comment">-- differentiation is linear
+</span> <span class="keyword">local</span> args = imap(diff,e,x)
+ <span class="keyword">return</span> balance(addi(args))
+ <span class="keyword">elseif</span> op == <span class="string">'*'</span> <span class="keyword">then</span> <span class="comment">-- product rule
+</span> <span class="keyword">local</span> res,d,ee = {}
+ <span class="keyword">for</span> i = <span class="number">1</span>,#e <span class="keyword">do</span>
+ d = fold(diff(e[i],x))
+ <span class="keyword">if</span> d ~= <span class="number">0</span> <span class="keyword">then</span>
+ ee = {<span class="global">unpack</span>(e)}
+ ee[i] = d
+ append(res,balance(muli(ee)))
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">if</span> #res &gt; <span class="number">1</span> <span class="keyword">then</span> <span class="keyword">return</span> addi(res)
+ <span class="keyword">else</span> <span class="keyword">return</span> res[<span class="number">1</span>] <span class="keyword">end</span>
+ <span class="keyword">elseif</span> op == <span class="string">'^'</span> <span class="keyword">and</span> isnumber(b) <span class="keyword">then</span> <span class="comment">-- power rule
+</span> <span class="keyword">return</span> b*x^(b-<span class="number">1</span>)
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> <span class="number">0</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span></pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/test-cmp.lua.html b/docs/examples/test-cmp.lua.html
new file mode 100644
index 0000000..59da691
--- /dev/null
+++ b/docs/examples/test-cmp.lua.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><strong>test-cmp.lua</strong></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>test-cmp.lua</h2>
+<pre>
+<span class="keyword">local</span> A = <span class="global">require</span> <span class="string">'pl.tablex'</span>
+<span class="global">print</span>(A.compare_no_order({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">2</span>,<span class="number">1</span>,<span class="number">3</span>}))
+<span class="global">print</span>(A.compare_no_order({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">2</span>,<span class="number">1</span>,<span class="number">3</span>},<span class="string">'=='</span>))</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/test-data.lua.html b/docs/examples/test-data.lua.html
new file mode 100644
index 0000000..031dd79
--- /dev/null
+++ b/docs/examples/test-data.lua.html
@@ -0,0 +1,373 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><strong>test-data.lua</strong></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>test-data.lua</h2>
+<pre>
+<span class="keyword">local</span> data = <span class="global">require</span> <span class="string">'pl.data'</span>
+<span class="keyword">local</span> List = <span class="global">require</span> <span class="string">'pl.List'</span>
+<span class="keyword">local</span> array = <span class="global">require</span> <span class="string">'pl.array2d'</span>
+<span class="keyword">local</span> func = <span class="global">require</span> <span class="string">'pl.func'</span>
+<span class="keyword">local</span> seq = <span class="global">require</span> <span class="string">'pl.seq'</span>
+<span class="keyword">local</span> stringio = <span class="global">require</span> <span class="string">'pl.stringio'</span>
+<span class="keyword">local</span> open = stringio. open
+<span class="keyword">local</span> asserteq = <span class="global">require</span> <span class="string">'pl.test'</span> . asserteq
+<span class="keyword">local</span> T = <span class="global">require</span> <span class="string">'pl.test'</span>. tuple
+
+<span class="comment">--[=[
+dat,err = data.read(open [[
+1.0 0.1
+0.2 1.3
+]])
+
+if err then print(err) end
+
+require 'pl.pretty'.dump(dat)
+os.exit(0)
+--]=]</span>
+
+<span class="comment">-- tab-separated data, explicit column names
+</span><span class="keyword">local</span> t1f = open <span class="string">[[
+EventID Magnitude LocationX LocationY LocationZ LocationError EventDate DataFile
+981124001 2.0 18988.4 10047.1 4149.7 33.8 24/11/1998 11:18:05 981124DF.AAB
+981125001 0.8 19104.0 9970.4 5088.7 3.0 25/11/1998 05:44:54 981125DF.AAB
+981127003 0.5 19012.5 9946.9 3831.2 46.0 27/11/1998 17:15:17 981127DF.AAD
+981127005 0.6 18676.4 10606.2 3761.9 4.4 27/11/1998 17:46:36 981127DF.AAF
+981127006 0.2 19109.9 9716.5 3612.0 11.8 27/11/1998 19:29:51 981127DF.AAG
+]]</span>
+
+<span class="keyword">local</span> t1 = data.read (t1f)
+<span class="comment">-- column_by_name returns a List
+</span>asserteq(t1:column_by_name <span class="string">'Magnitude'</span>,List{<span class="number">2</span>,<span class="number">0.8</span>,<span class="number">0.5</span>,<span class="number">0.6</span>,<span class="number">0.2</span>})
+<span class="comment">-- can use array.column as well
+</span>asserteq(array.column(t1,<span class="number">2</span>),{<span class="number">2</span>,<span class="number">0.8</span>,<span class="number">0.5</span>,<span class="number">0.6</span>,<span class="number">0.2</span>})
+
+<span class="comment">-- only numerical columns (deduced from first data row) are converted by default
+</span><span class="comment">-- can look up indices in the list fieldnames.
+</span><span class="keyword">local</span> EDI = t1.fieldnames:index <span class="string">'EventDate'</span>
+<span class="global">assert</span>(<span class="global">type</span>(t1[<span class="number">1</span>][EDI]) == <span class="string">'string'</span>)
+
+<span class="comment">-- select method returns a sequence, in this case single-valued.
+</span><span class="comment">-- (Note that seq.copy returns a List)
+</span>asserteq(seq(t1:<span class="global">select</span> <span class="string">'LocationX where Magnitude &gt; 0.5'</span>):copy(),List{<span class="number">18988.4</span>,<span class="number">19104</span>,<span class="number">18676.4</span>})
+
+<span class="comment">--[[
+--a common select usage pattern:
+for event,mag in t1:select 'EventID,Magnitude sort by Magnitude desc' do
+ print(event,mag)
+end
+--]]</span>
+
+<span class="comment">-- space-separated, but with last field containing spaces.
+</span><span class="keyword">local</span> t2f = open <span class="string">[[
+USER PID %MEM %CPU COMMAND
+sdonovan 2333 0.3 0.1 background --n=2
+root 2332 0.4 0.2 fred --start=yes
+root 2338 0.2 0.1 backyard-process
+]]</span>
+
+<span class="keyword">local</span> t2,err = data.read(t2f,{last_field_collect=<span class="keyword">true</span>})
+<span class="keyword">if</span> <span class="keyword">not</span> t2 <span class="keyword">then</span> <span class="keyword">return</span> <span class="global">print</span> (err) <span class="keyword">end</span>
+
+<span class="comment">-- the last_field_collect option is useful with space-delimited data where the last
+</span><span class="comment">-- field may contain spaces. Otherwise, a record count mismatch should be an error!
+</span><span class="keyword">local</span> lt2 = List(t2[<span class="number">2</span>])
+asserteq(lt2:join <span class="string">','</span>,<span class="string">'root,2332,0.4,0.2,fred --start=yes'</span>)
+
+<span class="comment">-- fieldnames are converted into valid identifiers by substituting _
+</span><span class="comment">-- (we do this to make select queries parseable by Lua)
+</span>asserteq(t2.fieldnames,List{<span class="string">'USER'</span>,<span class="string">'PID'</span>,<span class="string">'_MEM'</span>,<span class="string">'_CPU'</span>,<span class="string">'COMMAND'</span>})
+
+<span class="comment">-- select queries are NOT SQL so remember to use == ! (and no 'between' operator, sorry)
+</span><span class="comment">--s,err = t2:select('_MEM where USER="root"')
+</span><span class="comment">--assert(err == [[[string "tmp"]:9: unexpected symbol near '=']])
+</span>
+<span class="keyword">local</span> s = t2:<span class="global">select</span>(<span class="string">'_MEM where USER=="root"'</span>)
+<span class="global">assert</span>(s() == <span class="number">0.4</span>)
+<span class="global">assert</span>(s() == <span class="number">0.2</span>)
+<span class="global">assert</span>(s() == <span class="keyword">nil</span>)
+
+<span class="comment">-- CSV, Excel style. Double-quoted fields are allowed, and they may contain commas!
+</span><span class="keyword">local</span> t3f = open <span class="string">[[
+"Department Name","Employee ID",Project,"Hours Booked"
+sales,1231,overhead,4
+sales,1255,overhead,3
+engineering,1501,development,5
+engineering,1501,maintenance,3
+engineering,1433,maintenance,10
+]]</span>
+
+<span class="keyword">local</span> t3 = data.read(t3f,{csv=<span class="keyword">true</span>})
+
+<span class="comment">-- although fieldnames are turned in valid Lua identifiers, there is always <code>original_fieldnames</code>
+</span>asserteq(t3.fieldnames,List{<span class="string">'Department_Name'</span>,<span class="string">'Employee_ID'</span>,<span class="string">'Project'</span>,<span class="string">'Hours_Booked'</span>})
+asserteq(t3.original_fieldnames,List{<span class="string">'Department Name'</span>,<span class="string">'Employee ID'</span>,<span class="string">'Project'</span>,<span class="string">'Hours Booked'</span>})
+
+<span class="comment">-- a common operation is to select using a given list of columns, and each row
+</span><span class="comment">-- on some explicit condition. The select() method can take a table with these
+</span><span class="comment">-- parameters
+</span><span class="keyword">local</span> keepcols = {<span class="string">'Employee_ID'</span>,<span class="string">'Hours_Booked'</span>}
+
+<span class="keyword">local</span> q = t3:<span class="global">select</span> { fields = keepcols,
+ where = <span class="keyword">function</span>(row) <span class="keyword">return</span> row[<span class="number">1</span>]==<span class="string">'engineering'</span> <span class="keyword">end</span>
+ }
+
+asserteq(seq.copy2(q),{{<span class="number">1501</span>,<span class="number">5</span>},{<span class="number">1501</span>,<span class="number">3</span>},{<span class="number">1433</span>,<span class="number">10</span>}})
+
+<span class="comment">-- another pattern is doing a select to restrict rows &amp; columns, process some
+</span><span class="comment">-- fields and write out the modified rows.
+</span>
+<span class="keyword">local</span> outf = stringio.create()
+
+<span class="keyword">local</span> names = {[<span class="number">1501</span>]=<span class="string">'don'</span>,[<span class="number">1433</span>]=<span class="string">'dilbert'</span>}
+
+t3:write_row (outf,{<span class="string">'Employee'</span>,<span class="string">'Hours_Booked'</span>})
+q = t3:select_row {fields=keepcols,where=func.Eq(func._1[<span class="number">1</span>],<span class="string">'engineering'</span>)}
+<span class="keyword">for</span> row <span class="keyword">in</span> q <span class="keyword">do</span>
+ row[<span class="number">1</span>] = names[row[<span class="number">1</span>]]
+ t3:write_row(outf,row)
+<span class="keyword">end</span>
+
+asserteq(outf:value(),
+<span class="string">[[
+Employee,Hours_Booked
+don,5
+don,3
+dilbert,10
+]]</span>)
+
+<span class="comment">-- data may not always have column headers. When creating a data object
+</span><span class="comment">-- from a two-dimensional array, may specify the fieldnames, as a list or a string.
+</span><span class="comment">-- The delimiter is deduced from the fieldname string, so a string just containing
+</span><span class="comment">-- the delimiter will set it, and the fieldnames will be empty.
+</span><span class="keyword">local</span> dat = List()
+<span class="keyword">local</span> row = List.range(<span class="number">1</span>,<span class="number">10</span>)
+<span class="keyword">for</span> i = <span class="number">1</span>,<span class="number">10</span> <span class="keyword">do</span>
+ dat:append(row:map(<span class="string">'*'</span>,i))
+<span class="keyword">end</span>
+dat = data.new(dat,<span class="string">','</span>)
+<span class="keyword">local</span> out = stringio.create()
+dat:write(out,<span class="string">','</span>)
+asserteq(out:value(), <span class="string">[[
+1,2,3,4,5,6,7,8,9,10
+2,4,6,8,10,12,14,16,18,20
+3,6,9,12,15,18,21,24,27,30
+4,8,12,16,20,24,28,32,36,40
+5,10,15,20,25,30,35,40,45,50
+6,12,18,24,30,36,42,48,54,60
+7,14,21,28,35,42,49,56,63,70
+8,16,24,32,40,48,56,64,72,80
+9,18,27,36,45,54,63,72,81,90
+10,20,30,40,50,60,70,80,90,100
+]]</span>)
+
+<span class="comment">-- you can always use numerical field indices, AWK-style;
+</span><span class="comment">-- note how the copy_select method gives you a data object instead of an
+</span><span class="comment">-- iterator over the fields
+</span><span class="keyword">local</span> res = dat:copy_select <span class="string">'$1,$3 where $1 &gt; 5'</span>
+<span class="keyword">local</span> L = List
+asserteq(L(res),L{
+ L{<span class="number">6</span>, <span class="number">18</span>},
+ L{<span class="number">7</span>,<span class="number">21</span>},
+ L{<span class="number">8</span>,<span class="number">24</span>},
+ L{<span class="number">9</span>,<span class="number">27</span>},
+ L{<span class="number">10</span>,<span class="number">30</span>},
+})
+
+<span class="comment">-- the column_by_name method may take a fieldname or an index
+</span>asserteq(dat:column_by_name(<span class="number">2</span>), L{<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>,<span class="number">8</span>,<span class="number">10</span>,<span class="number">12</span>,<span class="number">14</span>,<span class="number">16</span>,<span class="number">18</span>,<span class="number">20</span>})
+
+<span class="comment">-- the field list may contain expressions or even constants
+</span><span class="keyword">local</span> q = dat:<span class="global">select</span> <span class="string">'$3,2*$4 where $1 == 8'</span>
+asserteq(T(q()),T(<span class="number">24</span>,<span class="number">64</span>))
+
+dat,err = data.read(open <span class="string">[[
+1.0 0.1
+0.2 1.3
+]]</span>)
+
+<span class="keyword">if</span> err <span class="keyword">then</span> <span class="global">print</span>(err) <span class="keyword">end</span>
+
+<span class="comment">-- if a method cannot be found, then we look up in array2d
+</span><span class="comment">-- array2d.flatten(t) makes a 1D list out of a 2D array,
+</span><span class="comment">-- and then List.minmax() gets the extrema.
+</span>
+asserteq(T(dat:flatten():minmax()),T(<span class="number">0.1</span>,<span class="number">1.3</span>))
+
+<span class="keyword">local</span> f = open <span class="string">[[
+Time Message
+1266840760 +# EE7C0600006F0D00C00F06010302054000000308010A00002B00407B00
+1266840760 closure data 0.000000 1972 1972 0
+1266840760 ++ 1266840760 EE 1
+1266840760 +# EE7C0600006F0D00C00F06010302054000000408020A00002B00407B00
+1266840764 closure data 0.000000 1972 1972 0
+1266840764 ++ 1266840764 EE 1
+1266840764 +# EE7C0600006F0D00C00F06010302054000000508030A00002B00407B00
+1266840768 duplicate?
+1266840768 +# EE7C0600006F0D00C00F06010302054000000508030A00002B00407B00
+1266840768 closure data 0.000000 1972 1972 0
+]]</span>
+
+<span class="comment">-- the <code>convert</code> option provides custom converters for each specified column.
+</span><span class="comment">-- Here we convert the timestamps into Date objects and collect everything
+</span><span class="comment">-- else into one field
+</span><span class="keyword">local</span> Date = <span class="global">require</span> <span class="string">'pl.Date'</span>
+
+<span class="keyword">local</span> <span class="keyword">function</span> date_convert (ds)
+ <span class="keyword">return</span> Date(<span class="global">tonumber</span>(ds))
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> d = data.read(f,{convert={[<span class="number">1</span>]=date_convert},last_field_collect=<span class="keyword">true</span>})
+
+asserteq(#d[<span class="number">1</span>],<span class="number">2</span>)
+asserteq(d[<span class="number">2</span>][<span class="number">1</span>]:year(),<span class="number">2010</span>)
+
+d = {{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}}
+out = stringio.create()
+data.write(d,out,{<span class="string">'A'</span>,<span class="string">'B'</span>,<span class="string">'C'</span>},<span class="string">','</span>)
+asserteq(out:value(),
+<span class="string">[[
+A,B,C
+1,2,3
+10,20,30
+]]</span>)
+
+out = stringio.create()
+d.fieldnames = {<span class="string">'A'</span>,<span class="string">'B'</span>,<span class="string">'C'</span>}
+data.write(d,out)
+
+asserteq(out:value(),
+<span class="string">[[
+A B C
+1 2 3
+10 20 30
+]]</span>)
+
+
+d = data.read(stringio.open <span class="string">'One,Two\n1,\n,20\n'</span>,{csv=<span class="keyword">true</span>})
+asserteq(d,{
+ {<span class="number">1</span>,<span class="number">0</span>},{<span class="number">0</span>,<span class="number">20</span>},
+ original_fieldnames={<span class="string">"One"</span>,<span class="string">"Two"</span>},fieldnames={<span class="string">"One"</span>,<span class="string">"Two"</span>},delim=<span class="string">","</span>
+})</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/test-listcallbacks.lua.html b/docs/examples/test-listcallbacks.lua.html
new file mode 100644
index 0000000..1e9e8b0
--- /dev/null
+++ b/docs/examples/test-listcallbacks.lua.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><strong>test-listcallbacks.lua</strong></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>test-listcallbacks.lua</h2>
+<pre>
+<span class="comment">-- demonstrates how to use a list of callbacks
+</span><span class="keyword">local</span> List = <span class="global">require</span> <span class="string">'pl.List'</span>
+<span class="keyword">local</span> utils = <span class="global">require</span> <span class="string">'pl.utils'</span>
+<span class="keyword">local</span> actions = List()
+<span class="keyword">local</span> L = utils.string_lambda
+
+actions:append(<span class="keyword">function</span>() <span class="global">print</span> <span class="string">'hello'</span> <span class="keyword">end</span>)
+actions:append(L <span class="string">'|| print "yay"'</span>)
+
+<span class="comment">-- '()' is a shortcut for operator.call or function(x) return x() end
+</span>actions:foreach <span class="string">'()'</span></pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/test-pretty.lua.html b/docs/examples/test-pretty.lua.html
new file mode 100644
index 0000000..fe555ac
--- /dev/null
+++ b/docs/examples/test-pretty.lua.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><strong>test-pretty.lua</strong></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>test-pretty.lua</h2>
+<pre>
+<span class="keyword">local</span> pretty = <span class="global">require</span> <span class="string">'pl.pretty'</span>
+
+<span class="keyword">local</span> tb = {
+ <span class="string">'one'</span>,<span class="string">'two'</span>,<span class="string">'three'</span>,{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},
+ alpha=<span class="number">1</span>,beta=<span class="number">2</span>,gamma=<span class="number">3</span>,[<span class="string">'&amp;'</span>]=<span class="keyword">true</span>,[<span class="number">0</span>]=<span class="keyword">false</span>,
+ _fred = {<span class="keyword">true</span>,<span class="keyword">true</span>},
+ s = <span class="string">[[
+hello dolly
+you're so fine
+]]</span>
+}
+
+<span class="global">print</span>(pretty.write(tb))</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/test-symbols.lua.html b/docs/examples/test-symbols.lua.html
new file mode 100644
index 0000000..8f0be26
--- /dev/null
+++ b/docs/examples/test-symbols.lua.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><strong>test-symbols.lua</strong></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>test-symbols.lua</h2>
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+<span class="comment">-- force us to look in the script's directory when requiring...
+</span>app.require_here()
+<span class="global">require</span> <span class="string">'symbols'</span>
+
+<span class="keyword">local</span> MT = <span class="global">getmetatable</span>(_1)
+
+add = MT.__add
+mul = MT.__mul
+pow = MT.__pow
+
+
+<span class="keyword">function</span> testeq (e1,e2)
+ <span class="keyword">if</span> <span class="keyword">not</span> equals(e1,e2) <span class="keyword">then</span>
+ <span class="global">print</span> (<span class="string">'Not equal'</span>,repr(e1),repr(e2))
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+sin = register(<span class="global">math</span>.sin,<span class="string">'sin'</span>)
+
+f = register(<span class="keyword">function</span>(x,y,z) <span class="keyword">end</span>)
+
+<span class="comment">--[[
+testeq (_1,_1)
+testeq (_1+_2,_1+_2)
+testeq (_1 + 3*_2,_1 + 3*_2)
+testeq (_2+_1,_1+_2)
+testeq (sin(_1),sin(_1))
+testeq (1+f(10,20,'ok'),f(10,20,'ok')+1)
+--]]</span>
+
+
+<span class="keyword">function</span> testexpand (e)
+ <span class="global">print</span>(repr(fold(expand(e)))) <span class="comment">--fold
+</span><span class="keyword">end</span>
+
+<span class="comment">--[[
+testexpand (a*(a+1))
+
+testexpand ((x+2)*(b+1))
+]]</span><span class="comment">--
+</span>
+<span class="keyword">function</span> testfold (e)
+ <span class="global">print</span>(repr(fold(e)))
+<span class="keyword">end</span>
+
+a,b,c,x,y = Var <span class="string">'a,b,c,x,y'</span>
+
+<span class="comment">--~ testfold(_1 + _2)
+</span><span class="comment">--~ testfold(add(10,20))
+</span><span class="comment">--~ testfold(add(mul(2,_1),mul(3,_2)))
+</span><span class="comment">--[[
+testfold(sin(a))
+e = a^(b+2)
+testfold(e)
+bindval(b,1)
+testfold(e)
+bindval(a,2)
+testfold(e)
+
+bindval(a)
+bindval(b)
+]]</span>
+
+
+
+<span class="keyword">function</span> testdiff (e)
+ balance(e)
+ e = diff(e,x)
+ balance(e)
+ <span class="global">print</span>(<span class="string">'+ '</span>,e)
+ e = fold(e)
+ <span class="global">print</span>(<span class="string">'- '</span>,e)
+<span class="keyword">end</span>
+
+
+testdiff(x^<span class="number">2</span>+<span class="number">1</span>)
+testdiff(<span class="number">3</span>*x^<span class="number">2</span>)
+testdiff(x^<span class="number">2</span> + <span class="number">2</span>*x^<span class="number">3</span>)
+testdiff(x^<span class="number">2</span> + <span class="number">2</span>*a*x^<span class="number">3</span> + x^<span class="number">4</span>)
+testdiff(<span class="number">2</span>*a*x^<span class="number">3</span>)
+testdiff(x*x*x)</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/testapp.lua.html b/docs/examples/testapp.lua.html
new file mode 100644
index 0000000..56ae5a3
--- /dev/null
+++ b/docs/examples/testapp.lua.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><strong>testapp.lua</strong></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>testapp.lua</h2>
+<pre>
+<span class="comment">-- shows how a script can get a private file path
+</span><span class="comment">-- the output on my Windows machine is:
+</span><span class="comment">-- C:\Documents and Settings\steve\.testapp\test.txt
+</span><span class="keyword">local</span> app = <span class="global">require</span> <span class="string">'pl.app'</span>
+<span class="global">print</span>(app.appfile <span class="string">'test.txt'</span>)</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/testclone.lua.html b/docs/examples/testclone.lua.html
new file mode 100644
index 0000000..aa6de87
--- /dev/null
+++ b/docs/examples/testclone.lua.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><strong>testclone.lua</strong></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>testclone.lua</h2>
+<pre>
+<span class="comment">--cloning a directory tree.
+</span><span class="keyword">local</span> lfs = <span class="global">require</span> <span class="string">'lfs'</span>
+<span class="keyword">local</span> path = <span class="global">require</span> <span class="string">'pl.path'</span>
+<span class="keyword">local</span> dir = <span class="global">require</span> <span class="string">'pl.dir'</span>
+
+<span class="keyword">local</span> p1 = <span class="string">[[examples]]</span>
+<span class="keyword">local</span> p2 = <span class="string">[[copy/of/examples]]</span>
+
+<span class="keyword">if</span> <span class="keyword">not</span> path.isfile <span class="string">'examples/testclone.lua'</span> <span class="keyword">then</span>
+ <span class="keyword">return</span> <span class="global">print</span> <span class="string">'please run this in the penlight folder (below examples)'</span>
+<span class="keyword">end</span>
+
+<span class="comment">-- make a copy of the examples folder
+</span>dir.clonetree(p1,p2,dir.copyfile)
+
+<span class="global">assert</span>(path.isdir <span class="string">'copy'</span>)
+
+<span class="global">print</span> <span class="string">'---'</span>
+<span class="keyword">local</span> t = <span class="global">os</span>.time()
+<span class="global">print</span>(lfs.touch(<span class="string">'examples/testclone.lua'</span>,t,t+<span class="number">10</span>))
+
+<span class="comment">-- this should only update this file
+</span>dir.clonetree(p1,p2,
+<span class="keyword">function</span>(f1,f2)
+ <span class="keyword">local</span> t1 = path.getmtime(f1)
+ <span class="keyword">local</span> t2 = path.getmtime(f2)
+ <span class="comment">--print(f1,t1,f2,t2)
+</span> <span class="keyword">if</span> t1 &gt; t2 <span class="keyword">then</span>
+ dir.copyfile(f1,f2)
+ <span class="global">print</span>(f1,f2,t1,t2)
+ <span class="keyword">end</span>
+ <span class="keyword">return</span> <span class="keyword">true</span>
+<span class="keyword">end</span>)
+
+<span class="comment">-- and get rid of the whole copy directory, with subdirs
+</span>dir.rmtree <span class="string">'copy'</span>
+
+<span class="global">assert</span>(<span class="keyword">not</span> path.exists <span class="string">'copy'</span>)</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/testconfig.lua.html b/docs/examples/testconfig.lua.html
new file mode 100644
index 0000000..39e32e3
--- /dev/null
+++ b/docs/examples/testconfig.lua.html
@@ -0,0 +1,177 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><strong>testconfig.lua</strong></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>testconfig.lua</h2>
+<pre>
+<span class="keyword">local</span> stringio = <span class="global">require</span> <span class="string">'pl.stringio'</span>
+<span class="keyword">local</span> config = <span class="global">require</span> <span class="string">'pl.config'</span>
+
+<span class="keyword">local</span> <span class="keyword">function</span> dump(t,indent)
+ <span class="keyword">if</span> <span class="global">type</span>(t) == <span class="string">'table'</span> <span class="keyword">then</span>
+ <span class="global">io</span>.write(indent,<span class="string">'{\n'</span>)
+ <span class="keyword">local</span> newindent = indent..<span class="string">' '</span>
+ <span class="keyword">for</span> k,v <span class="keyword">in</span> <span class="global">pairs</span>(t) <span class="keyword">do</span>
+ <span class="global">io</span>.write(newindent,k,<span class="string">'='</span>)
+ dump(v,indent)
+ <span class="global">io</span>.write(<span class="string">'\n'</span>)
+ <span class="keyword">end</span>
+ <span class="global">io</span>.write(newindent,<span class="string">'},\n'</span>)
+ <span class="keyword">else</span>
+ <span class="global">io</span>.write(indent,t,<span class="string">'('</span>,<span class="global">type</span>(t),<span class="string">')'</span>)
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+
+<span class="keyword">local</span> <span class="keyword">function</span> testconfig(test)
+ <span class="keyword">local</span> f = stringio.open(test)
+ <span class="keyword">local</span> c = config.read(f)
+ f:close()
+ dump(c,<span class="string">' '</span>)
+ <span class="global">print</span> <span class="string">'-----'</span>
+<span class="keyword">end</span>
+
+testconfig <span class="string">[[
+ ; comment 2 (an ini file)
+[section!]
+bonzo.dog=20,30
+config_parm=here we go again
+depth = 2
+[another]
+felix="cat"
+]]</span>
+
+testconfig <span class="string">[[
+# this is a more Unix-y config file
+fred = 1
+alice = 2
+home = /bonzo/dog/etc
+]]</span>
+
+testconfig <span class="string">[[
+# this is just a set of comma-separated values
+1000,444,222
+44,555,224
+]]</span></pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/testglobal.lua.html b/docs/examples/testglobal.lua.html
new file mode 100644
index 0000000..5618f98
--- /dev/null
+++ b/docs/examples/testglobal.lua.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><strong>testglobal.lua</strong></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>testglobal.lua</h2>
+<pre>
+<span class="comment">-- very simple lexer program which looks at all identifiers in a Lua
+</span><span class="comment">-- file and checks whether they're in the global namespace.
+</span><span class="comment">-- At the end, we dump out the result of count_map, which will give us
+</span><span class="comment">-- unique identifiers with their usage count.
+</span><span class="comment">-- (an example of a program which itself needs to be careful about what
+</span><span class="comment">-- goes into the global namespace)
+</span>
+<span class="keyword">local</span> utils = <span class="global">require</span> <span class="string">'pl.utils'</span>
+<span class="keyword">local</span> file = <span class="global">require</span> <span class="string">'pl.file'</span>
+<span class="keyword">local</span> lexer = <span class="global">require</span> <span class="string">'pl.lexer'</span>
+<span class="keyword">local</span> List = <span class="global">require</span> <span class="string">'pl.List'</span>
+<span class="keyword">local</span> pretty = <span class="global">require</span> <span class="string">'pl.pretty'</span>
+<span class="keyword">local</span> seq = <span class="global">require</span> <span class="string">'pl.seq'</span>
+<span class="keyword">local</span> path = <span class="global">require</span> <span class="string">'pl.path'</span>
+
+utils.on_error <span class="string">'quit'</span>
+
+<span class="keyword">local</span> txt = file.read(arg[<span class="number">1</span>] <span class="keyword">or</span> path.normpath(<span class="string">'examples/testglobal.lua'</span>))
+<span class="keyword">local</span> globals = List()
+<span class="keyword">for</span> t,v <span class="keyword">in</span> lexer.lua(txt) <span class="keyword">do</span>
+ <span class="keyword">if</span> t == <span class="string">'iden'</span> <span class="keyword">and</span> <span class="global">rawget</span>(_G,v) <span class="keyword">then</span>
+ globals:append(v)
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+pretty.dump(seq.count_map(globals))</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/testinputfields.lua.html b/docs/examples/testinputfields.lua.html
new file mode 100644
index 0000000..fad1770
--- /dev/null
+++ b/docs/examples/testinputfields.lua.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><strong>testinputfields.lua</strong></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>testinputfields.lua</h2>
+<pre>
+<span class="keyword">local</span> input = <span class="global">require</span> <span class="string">'pl.input'</span>
+<span class="keyword">local</span> sum = <span class="number">0.0</span>
+<span class="keyword">local</span> count = <span class="number">0</span>
+<span class="keyword">local</span> text = <span class="string">[[
+ 981124001 2.0 18988.4 10047.1 4149.7
+ 981125001 0.8 19104.0 9970.4 5088.7
+ 981127003 0.5 19012.5 9946.9 3831.2
+]]</span>
+<span class="keyword">for</span> id,magn,x <span class="keyword">in</span> input.fields(<span class="number">3</span>,<span class="string">' '</span>,text) <span class="keyword">do</span>
+ sum = sum + x
+ count = count + <span class="number">1</span>
+<span class="keyword">end</span>
+<span class="global">print</span>(<span class="string">'average x coord is '</span>,sum/count)</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/testinputfields2.lua.html b/docs/examples/testinputfields2.lua.html
new file mode 100644
index 0000000..9081ae1
--- /dev/null
+++ b/docs/examples/testinputfields2.lua.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><strong>testinputfields2.lua</strong></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>testinputfields2.lua</h2>
+<pre>
+<span class="keyword">local</span> input = <span class="global">require</span> <span class="string">'pl.input'</span>
+<span class="keyword">local</span> seq = <span class="global">require</span> <span class="string">'pl.seq'</span>
+<span class="keyword">local</span> text = <span class="string">[[
+ 981124001 2.0 18988.4 10047.1 4149.7
+ 981125001 0.8 19104.0 9970.4 5088.7
+ 981127003 0.5 19012.5 9946.9 3831.2
+]]</span>
+<span class="keyword">local</span> sum,count = seq.sum(input.fields ({<span class="number">3</span>},<span class="string">' '</span>,text))
+<span class="global">print</span>(sum/count)</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/testxml.lua.html b/docs/examples/testxml.lua.html
new file mode 100644
index 0000000..d07dfa4
--- /dev/null
+++ b/docs/examples/testxml.lua.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><strong>testxml.lua</strong></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>testxml.lua</h2>
+<pre>
+<span class="comment">-- an example showing 'pl.lexer' doing some serious work.
+</span><span class="comment">-- The resulting Lua table is in the same LOM format used by luaexpat.
+</span><span class="comment">-- This is (clearly) not a professional XML parser, so don't use it
+</span><span class="comment">-- on your homework!
+</span>
+<span class="keyword">local</span> lexer = <span class="global">require</span> <span class="string">'pl.lexer'</span>
+<span class="keyword">local</span> pretty = <span class="global">require</span> <span class="string">'pl.pretty'</span>
+
+<span class="keyword">local</span> append = <span class="global">table</span>.insert
+<span class="keyword">local</span> skipws,expecting = lexer.skipws,lexer.expecting
+
+<span class="keyword">local</span> <span class="keyword">function</span> parse_element (tok,tag)
+ <span class="keyword">local</span> tbl,t,v,attrib
+ tbl = {}
+ tbl.tag = tag <span class="comment">-- LOM 'tag' is the element tag
+</span> t,v = skipws(tok)
+ <span class="keyword">while</span> v ~= <span class="string">'/'</span> <span class="keyword">and</span> v ~= <span class="string">'&gt;'</span> <span class="keyword">do</span>
+ <span class="keyword">if</span> t ~= <span class="string">'iden'</span> <span class="keyword">then</span> <span class="global">error</span>(<span class="string">'expecting attribute identifier'</span>) <span class="keyword">end</span>
+ attrib = v
+ expecting(tok,<span class="string">'='</span>)
+ v = expecting(tok,<span class="string">'string'</span>)
+ <span class="comment">-- LOM: 'attr' subtable contains attrib/value pairs and an ordered list of attribs
+</span> <span class="keyword">if</span> <span class="keyword">not</span> tbl.attr <span class="keyword">then</span> tbl.attr = {} <span class="keyword">end</span>
+ tbl.attr[attrib] = v
+ append(tbl.attr,attrib)
+ t,v = skipws(tok)
+ <span class="keyword">end</span>
+ <span class="keyword">if</span> v == <span class="string">'/'</span> <span class="keyword">then</span>
+ expecting(tok,<span class="string">'&gt;'</span>)
+ <span class="keyword">return</span> tbl
+ <span class="keyword">end</span>
+ <span class="comment">-- pick up element data
+</span> t,v = tok()
+ <span class="keyword">while</span> <span class="keyword">true</span> <span class="keyword">do</span>
+ <span class="keyword">if</span> t == <span class="string">'&lt;'</span> <span class="keyword">then</span>
+ t,v = skipws(tok)
+ <span class="keyword">if</span> t == <span class="string">'/'</span> <span class="keyword">then</span> <span class="comment">-- element end tag
+</span> t,v = tok()
+ <span class="keyword">if</span> t == <span class="string">'&gt;'</span> <span class="keyword">then</span> <span class="keyword">return</span> tbl <span class="keyword">end</span>
+ <span class="keyword">if</span> t == <span class="string">'iden'</span> <span class="keyword">and</span> v == tag <span class="keyword">then</span>
+ <span class="keyword">if</span> tok() == <span class="string">'&gt;'</span> <span class="keyword">then</span> <span class="keyword">return</span> tbl <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="global">error</span>(<span class="string">'expecting end tag '</span>..tag)
+ <span class="keyword">else</span>
+ append(tbl,parse_element(tok,v)) <span class="comment">-- LOM: child elements added to table
+</span> t,v = skipws(tok)
+ <span class="keyword">end</span>
+ <span class="keyword">else</span>
+ append(tbl,v) <span class="comment">-- LOM: text added to table
+</span> t,v = skipws(tok)
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> <span class="keyword">function</span> parse_xml (tok)
+ <span class="keyword">local</span> t = skipws(tok)
+ <span class="keyword">local</span> v
+ <span class="keyword">while</span> t == <span class="string">'&lt;'</span> <span class="keyword">do</span>
+ t,v = tok()
+ <span class="keyword">if</span> t == <span class="string">'?'</span> <span class="keyword">or</span> t == <span class="string">'!'</span> <span class="keyword">then</span>
+ <span class="comment">-- skip meta stuff and commentary
+</span> <span class="keyword">repeat</span> t = tok() <span class="keyword">until</span> t == <span class="string">'&gt;'</span>
+ t = expecting(tok,<span class="string">'&lt;'</span>)
+ <span class="keyword">else</span>
+ <span class="keyword">return</span> parse_element(tok,v)
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> s = <span class="string">[[
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;sensor name="closure-meter-2" id="7D7D0600006F0D00" loc="100,100,0" device="closure-meter" init="true"&gt;
+&lt;detector name="closure-meter" phenomenon="closure" units="mm" id="1"
+ vmin="0" vmax="5000" device="closure-meter" calib="0,0;5000,5000"
+ sampling_interval="25000" measurement_interval="600000"
+/&gt;
+&lt;/sensor&gt;
+]]</span>
+
+<span class="keyword">local</span> tok = lexer.scan(s,<span class="keyword">nil</span>,{space=<span class="keyword">false</span>},{<span class="global">string</span>=<span class="keyword">true</span>})
+<span class="keyword">local</span> res = parse_xml(tok)
+<span class="global">print</span>(pretty.write(res))</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/examples/which.lua.html b/docs/examples/which.lua.html
new file mode 100644
index 0000000..2b4b848
--- /dev/null
+++ b/docs/examples/which.lua.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><strong>which.lua</strong></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>which.lua</h2>
+<pre>
+<span class="comment">-- a simple implementation of the which command. This looks for
+</span><span class="comment">-- the given file on the path. On windows, it will assume an extension
+</span><span class="comment">-- of .exe if no extension is given.
+</span><span class="keyword">local</span> List = <span class="global">require</span> <span class="string">'pl.List'</span>
+<span class="keyword">local</span> path = <span class="global">require</span> <span class="string">'pl.path'</span>
+<span class="keyword">local</span> app = <span class="global">require</span> <span class="string">'pl.app'</span>
+
+<span class="keyword">local</span> pathl = List.split(<span class="global">os</span>.getenv <span class="string">'PATH'</span>,path.dirsep)
+
+<span class="keyword">local</span> <span class="keyword">function</span> which (file)
+ <span class="keyword">local</span> res = pathl:map(path.join,file)
+ res = res:filter(path.exists)
+ <span class="keyword">if</span> res <span class="keyword">then</span> <span class="keyword">return</span> res[<span class="number">1</span>] <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> _,lua = app.lua()
+<span class="keyword">local</span> file = arg[<span class="number">1</span>] <span class="keyword">or</span> lua <span class="comment">-- i.e. location of lua executable
+</span><span class="keyword">local</span> try
+
+<span class="keyword">if</span> <span class="keyword">not</span> file <span class="keyword">then</span> <span class="keyword">return</span> <span class="global">print</span> <span class="string">'must provide a filename'</span> <span class="keyword">end</span>
+
+<span class="keyword">if</span> path.extension(file) == <span class="string">''</span> <span class="keyword">and</span> path.is_windows <span class="keyword">then</span>
+ try = which(file..<span class="string">'.exe'</span>)
+<span class="keyword">else</span>
+ try = which(file)
+<span class="keyword">end</span>
+
+<span class="keyword">if</span> try <span class="keyword">then</span> <span class="global">print</span>(try) <span class="keyword">else</span> <span class="global">print</span> <span class="string">'cannot find on path'</span> <span class="keyword">end</span></pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..d241189
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,394 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="libraries/pl.html">pl</a></li>
+ <li><a href="libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="libraries/pl.app.html">pl.app</a></li>
+ <li><a href="libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="libraries/pl.class.html">pl.class</a></li>
+ <li><a href="libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="libraries/pl.config.html">pl.config</a></li>
+ <li><a href="libraries/pl.data.html">pl.data</a></li>
+ <li><a href="libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="libraries/pl.file.html">pl.file</a></li>
+ <li><a href="libraries/pl.func.html">pl.func</a></li>
+ <li><a href="libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="libraries/pl.input.html">pl.input</a></li>
+ <li><a href="libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="libraries/pl.path.html">pl.path</a></li>
+ <li><a href="libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="libraries/pl.template.html">pl.template</a></li>
+ <li><a href="libraries/pl.test.html">pl.test</a></li>
+ <li><a href="libraries/pl.text.html">pl.text</a></li>
+ <li><a href="libraries/pl.types.html">pl.types</a></li>
+ <li><a href="libraries/pl.url.html">pl.url</a></li>
+ <li><a href="libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="classes/pl.List.html">pl.List</a></li>
+ <li><a href="classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="manual/06-data.md.html">Data</a></li>
+ <li><a href="manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+
+ <h2>Penlight Lua Libraries 1.6.0</h2>
+ <p>The documentation is available <a href="manual/01-introduction.md.html#">here</a>.</p>
+
+<h2>Libraries</h2>
+<table class="module_list">
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.html">pl</a></td>
+ <td class="summary">Entry point for loading all PL libraries only on demand, into the global space.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.Set.html">pl.Set</a></td>
+ <td class="summary">A Set class.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.app.html">pl.app</a></td>
+ <td class="summary">Application support functions.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.array2d.html">pl.array2d</a></td>
+ <td class="summary">Operations on two-dimensional arrays.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.class.html">pl.class</a></td>
+ <td class="summary">Provides a reuseable and convenient framework for creating classes in Lua.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.compat.html">pl.compat</a></td>
+ <td class="summary">Lua 5.1/5.2/5.3 compatibility.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.comprehension.html">pl.comprehension</a></td>
+ <td class="summary">List comprehensions implemented in Lua.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.config.html">pl.config</a></td>
+ <td class="summary">Reads configuration files into a Lua table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.data.html">pl.data</a></td>
+ <td class="summary">Reading and querying simple tabular data.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.dir.html">pl.dir</a></td>
+ <td class="summary">Listing files in directories and creating/removing directory paths.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.file.html">pl.file</a></td>
+ <td class="summary">File manipulation functions: reading, writing, moving and copying.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.func.html">pl.func</a></td>
+ <td class="summary">Functional helpers like composition, binding and placeholder expressions.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.import_into.html">pl.import_into</a></td>
+ <td class="summary">PL loader, for loading all PL libraries, only on demand.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.input.html">pl.input</a></td>
+ <td class="summary">Iterators for extracting words or numbers from an input source.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.lapp.html">pl.lapp</a></td>
+ <td class="summary">Simple command-line parsing using human-readable specification.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.lexer.html">pl.lexer</a></td>
+ <td class="summary">Lexical scanner for creating a sequence of tokens from text.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.luabalanced.html">pl.luabalanced</a></td>
+ <td class="summary">Extract delimited Lua sequences from strings.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.operator.html">pl.operator</a></td>
+ <td class="summary">Lua operators available as functions.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.path.html">pl.path</a></td>
+ <td class="summary">Path manipulation and file queries.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.permute.html">pl.permute</a></td>
+ <td class="summary">Permutation operations.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.pretty.html">pl.pretty</a></td>
+ <td class="summary">Pretty-printing Lua tables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.seq.html">pl.seq</a></td>
+ <td class="summary">Manipulating iterators as sequences.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.sip.html">pl.sip</a></td>
+ <td class="summary">Simple Input Patterns (SIP).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.strict.html">pl.strict</a></td>
+ <td class="summary">Checks uses of undeclared global variables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.stringio.html">pl.stringio</a></td>
+ <td class="summary">Reading and writing strings using file-like objects.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.stringx.html">pl.stringx</a></td>
+ <td class="summary">Python-style extended string library.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.tablex.html">pl.tablex</a></td>
+ <td class="summary">Extended operations on Lua tables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.template.html">pl.template</a></td>
+ <td class="summary">A template preprocessor.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.test.html">pl.test</a></td>
+ <td class="summary">Useful test utilities.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.text.html">pl.text</a></td>
+ <td class="summary">Text processing utilities.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.types.html">pl.types</a></td>
+ <td class="summary">Dealing with Detailed Type Information</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.url.html">pl.url</a></td>
+ <td class="summary">Python-style URL quoting library.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.utils.html">pl.utils</a></td>
+ <td class="summary">Generally useful routines.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="libraries/pl.xml.html">pl.xml</a></td>
+ <td class="summary">XML LOM Utilities.</td>
+ </tr>
+</table>
+<h2>Classes</h2>
+<table class="module_list">
+ <tr>
+ <td class="name" nowrap><a href="classes/pl.Date.html">pl.Date</a></td>
+ <td class="summary">Date and Date Format classes.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="classes/pl.List.html">pl.List</a></td>
+ <td class="summary">Python-style list class.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="classes/pl.Map.html">pl.Map</a></td>
+ <td class="summary">A Map class.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="classes/pl.MultiMap.html">pl.MultiMap</a></td>
+ <td class="summary">MultiMap, a Map which has multiple values per key.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="classes/pl.OrderedMap.html">pl.OrderedMap</a></td>
+ <td class="summary">OrderedMap, a map which preserves ordering.</td>
+ </tr>
+</table>
+<h2>Manual</h2>
+<table class="module_list">
+ <tr>
+ <td class="name" nowrap><a href="manual/01-introduction.md.html">01-introduction.md</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="manual/02-arrays.md.html">02-arrays.md</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="manual/03-strings.md.html">03-strings.md</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="manual/04-paths.md.html">04-paths.md</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="manual/05-dates.md.html">05-dates.md</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="manual/06-data.md.html">06-data.md</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="manual/07-functional.md.html">07-functional.md</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="manual/08-additional.md.html">08-additional.md</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="manual/09-discussion.md.html">09-discussion.md</a></td>
+ <td class="summary"></td>
+ </tr>
+</table>
+<h2>Examples</h2>
+<table class="module_list">
+ <tr>
+ <td class="name" nowrap><a href="examples/seesubst.lua.html">seesubst.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/sipscan.lua.html">sipscan.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/symbols.lua.html">symbols.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/test-cmp.lua.html">test-cmp.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/test-data.lua.html">test-data.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/test-pretty.lua.html">test-pretty.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/test-symbols.lua.html">test-symbols.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/testapp.lua.html">testapp.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/testclone.lua.html">testclone.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/testconfig.lua.html">testconfig.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/testglobal.lua.html">testglobal.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/testinputfields.lua.html">testinputfields.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/testinputfields2.lua.html">testinputfields2.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/testxml.lua.html">testxml.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="examples/which.lua.html">which.lua</a></td>
+ <td class="summary"></td>
+ </tr>
+</table>
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/ldoc_fixed.css b/docs/ldoc_fixed.css
new file mode 100644
index 0000000..9b0fc00
--- /dev/null
+++ b/docs/ldoc_fixed.css
@@ -0,0 +1,311 @@
+/* BEGIN RESET
+
+Copyright (c) 2010, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.8.2r1
+*/
+html {
+ color: #000;
+ background: #FFF;
+}
+body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td {
+ margin: 0;
+ padding: 0;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+fieldset,img {
+ border: 0;
+}
+address,caption,cite,code,dfn,em,strong,th,var,optgroup {
+ font-style: inherit;
+ font-weight: inherit;
+}
+del,ins {
+ text-decoration: none;
+}
+li {
+ margin-left: 20px;
+}
+caption,th {
+ text-align: left;
+}
+h1,h2,h3,h4,h5,h6 {
+ font-size: 100%;
+ font-weight: bold;
+}
+q:before,q:after {
+ content: '';
+}
+abbr,acronym {
+ border: 0;
+ font-variant: normal;
+}
+sup {
+ vertical-align: baseline;
+}
+sub {
+ vertical-align: baseline;
+}
+legend {
+ color: #000;
+}
+input,button,textarea,select,optgroup,option {
+ font-family: inherit;
+ font-size: inherit;
+ font-style: inherit;
+ font-weight: inherit;
+}
+input,button,textarea,select {*font-size:100%;
+}
+/* END RESET */
+
+body {
+ margin-left: 1em;
+ margin-right: 1em;
+ font-family: arial, helvetica, geneva, sans-serif;
+ background-color: #ffffff; margin: 0px;
+}
+
+code, tt { font-family: monospace; font-size: 1.1em; }
+span.parameter { font-family:monospace; }
+span.parameter:after { content:":"; }
+span.types:before { content:"("; }
+span.types:after { content:")"; }
+.type { font-weight: bold; font-style:italic }
+
+body, p, td, th { font-size: .95em; line-height: 1.2em;}
+
+p, ul { margin: 10px 0 0 0px;}
+
+strong { font-weight: bold;}
+
+em { font-style: italic;}
+
+h1 {
+ font-size: 1.5em;
+ margin: 0 0 20px 0;
+}
+h2, h3, h4 { margin: 15px 0 10px 0; }
+h2 { font-size: 1.25em; }
+h3 { font-size: 1.15em; }
+h4 { font-size: 1.06em; }
+
+a:link { font-weight: bold; color: #004080; text-decoration: none; }
+a:visited { font-weight: bold; color: #006699; text-decoration: none; }
+a:link:hover { text-decoration: underline; }
+
+hr {
+ color:#cccccc;
+ background: #00007f;
+ height: 1px;
+}
+
+blockquote { margin-left: 3em; }
+
+ul { list-style-type: disc; }
+
+p.name {
+ font-family: "Andale Mono", monospace;
+ padding-top: 1em;
+}
+
+pre {
+ background-color: rgb(245, 245, 245);
+ border: 1px solid #C0C0C0; /* silver */
+ padding: 10px;
+ margin: 10px 0 10px 0;
+ overflow: auto;
+ font-family: "Andale Mono", monospace;
+}
+
+pre.example {
+ font-size: .85em;
+}
+
+table.index { border: 1px #00007f; }
+table.index td { text-align: left; vertical-align: top; }
+
+#container {
+ margin-left: 1em;
+ margin-right: 1em;
+ background-color: #ffffff;
+}
+
+#product {
+ text-align: center;
+ border-bottom: 1px solid #cccccc;
+ background-color: #ffffff;
+}
+
+#product big {
+ font-size: 2em;
+}
+
+#main {
+ background-color:#FFFFFF; // #f0f0f0;
+ border-left: 1px solid #cccccc;
+}
+
+#navigation {
+ position: fixed;
+ top: 0;
+ left: 0;
+ float: left;
+ width: 14em;
+ vertical-align: top;
+ background-color:#FFFFFF; // #f0f0f0;
+ border-right: 2px solid #cccccc;
+ overflow: visible;
+ overflow-y: scroll;
+ height: 100%;
+ padding-left: 1em;
+}
+
+#navigation h2 {
+ background-color:#FFFFFF;//:#e7e7e7;
+ font-size:1.1em;
+ color:#000000;
+ text-align: left;
+ padding:0.2em;
+ border-bottom:1px solid #dddddd;
+}
+
+#navigation ul
+{
+ font-size:1em;
+ list-style-type: none;
+ margin: 1px 1px 10px 1px;
+}
+
+#navigation li {
+ text-indent: -1em;
+ display: block;
+ margin: 3px 0px 0px 22px;
+}
+
+#navigation li li a {
+ margin: 0px 3px 0px -1em;
+}
+
+#content {
+ margin-left: 14em;
+ padding: 1em;
+ padding-left: 2em;
+ width: 700px;
+ border-left: 2px solid #cccccc;
+ // border-right: 2px solid #cccccc;
+ background-color: #ffffff;
+}
+
+#about {
+ clear: both;
+ padding-left: 1em;
+ margin-left: 14em; // avoid the damn sidebar!
+ border-top: 2px solid #cccccc;
+ border-left: 2px solid #cccccc;
+ background-color: #ffffff;
+}
+
+@media print {
+ body {
+ font: 12pt "Times New Roman", "TimeNR", Times, serif;
+ }
+ a { font-weight: bold; color: #004080; text-decoration: underline; }
+
+ #main {
+ background-color: #ffffff;
+ border-left: 0px;
+ }
+
+ #container {
+ margin-left: 2%;
+ margin-right: 2%;
+ background-color: #ffffff;
+ }
+
+ #content {
+ padding: 1em;
+ background-color: #ffffff;
+ }
+
+ #navigation {
+ display: none;
+ }
+ pre.example {
+ font-family: "Andale Mono", monospace;
+ font-size: 10pt;
+ page-break-inside: avoid;
+ }
+}
+
+table.module_list {
+ border-width: 1px;
+ border-style: solid;
+ border-color: #cccccc;
+ border-collapse: collapse;
+}
+table.module_list td {
+ border-width: 1px;
+ padding: 3px;
+ border-style: solid;
+ border-color: #cccccc;
+}
+table.module_list td.name { background-color: #f0f0f0; ; min-width: 200px; }
+table.module_list td.summary { width: 100%; }
+
+table.function_list {
+ border-width: 1px;
+ border-style: solid;
+ border-color: #cccccc;
+ border-collapse: collapse;
+}
+table.function_list td {
+ border-width: 1px;
+ padding: 3px;
+ border-style: solid;
+ border-color: #cccccc;
+}
+table.function_list td.name { background-color: #f6f6ff; ; min-width: 200px; }
+table.function_list td.summary { width: 100%; }
+
+dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
+dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
+dl.table h3, dl.function h3 {font-size: .95em;}
+
+ul.nowrap {
+ overflow:auto;
+ whitespace:nowrap;
+}
+
+/* stop sublists from having initial vertical space */
+ul ul { margin-top: 0px; }
+ol ul { margin-top: 0px; }
+ol ol { margin-top: 0px; }
+ul ol { margin-top: 0px; }
+
+/* make the target distinct; helps when we're navigating to a function */
+a:target + * {
+ background-color: #FF9;
+}
+
+
+/* styles for prettification of source */
+pre .comment { color: #558817; }
+pre .constant { color: #a8660d; }
+pre .escape { color: #844631; }
+pre .keyword { color: #aa5050; font-weight: bold; }
+pre .library { color: #0e7c6b; }
+pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
+pre .string { color: #8080ff; }
+pre .number { color: #f8660d; }
+pre .operator { color: #2239a8; font-weight: bold; }
+pre .preprocessor, pre .prepro { color: #a33243; }
+pre .global { color: #800080; }
+pre .user-keyword { color: #800080; }
+pre .prompt { color: #558817; }
+pre .url { color: #272fc2; text-decoration: underline; }
+
diff --git a/docs/libraries/pl.Set.html b/docs/libraries/pl.Set.html
new file mode 100644
index 0000000..8eda41e
--- /dev/null
+++ b/docs/libraries/pl.Set.html
@@ -0,0 +1,650 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+<li><a href="#metamethods">metamethods</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><strong>pl.Set</strong></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.Set</code></h1>
+<p>A Set class.</p>
+<p>
+
+<pre>
+&gt; Set = <span class="global">require</span> <span class="string">'pl.Set'</span>
+&gt; = Set{<span class="string">'one'</span>,<span class="string">'two'</span>} == Set{<span class="string">'two'</span>,<span class="string">'one'</span>}
+<span class="keyword">true</span>
+&gt; fruit = Set{<span class="string">'apple'</span>,<span class="string">'banana'</span>,<span class="string">'orange'</span>}
+&gt; = fruit[<span class="string">'banana'</span>]
+<span class="keyword">true</span>
+&gt; = fruit[<span class="string">'hazelnut'</span>]
+<span class="keyword">nil</span>
+&gt; colours = Set{<span class="string">'red'</span>,<span class="string">'orange'</span>,<span class="string">'green'</span>,<span class="string">'blue'</span>}
+&gt; = fruit,colours
+[apple,orange,banana] [blue,green,orange,red]
+&gt; = fruit+colours
+[blue,green,apple,red,orange,banana]
+[orange]
+&gt; more_fruits = fruit + <span class="string">'apricot'</span>
+&gt; = fruit*colours
+ = more_fruits, fruit
+banana,apricot,apple,orange] [banana,apple,orange]
+</pre>
+
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.tablex.html#">pl.tablex</a>, <a href="../libraries/pl.class.html#">pl.class</a>, <a href="../classes/pl.Map.html#">pl.Map</a>, (<a href="../classes/pl.List.html#">pl.List</a> if __tostring is used)</p></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#Set">Set (t)</a></td>
+ <td class="summary">create a set.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#values">values (self)</a></td>
+ <td class="summary">get a list of the values in a set.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#map">map (self, fn, ...)</a></td>
+ <td class="summary">map a function over the values of a set.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#union">union (self, set)</a></td>
+ <td class="summary">union of two sets (also +).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#intersection">intersection (self, set)</a></td>
+ <td class="summary">intersection of two sets (also *).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#difference">difference (self, set)</a></td>
+ <td class="summary">new set with elements in the set that are not in the other (also -).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#issubset">issubset (self, set)</a></td>
+ <td class="summary">is the first set a subset of the second (also &lt;)?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isempty">isempty (self)</a></td>
+ <td class="summary">is the set empty?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isdisjoint">isdisjoint (s1, s2)</a></td>
+ <td class="summary">are the sets disjoint?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#len">len (s)</a></td>
+ <td class="summary">size of this set (also # for 5.2).</td>
+ </tr>
+</table>
+<h2><a href="#metamethods">metamethods</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#__tostring">__tostring ()</a></td>
+ <td class="summary">string representation of a set.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#__add">__add ()</a></td>
+ <td class="summary">union of sets.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#__mul">__mul ()</a></td>
+ <td class="summary">intersection of sets.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#__sub">__sub ()</a></td>
+ <td class="summary">difference of sets.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#__pow">__pow ()</a></td>
+ <td class="summary">symmetric difference of sets.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#__lt">__lt ()</a></td>
+ <td class="summary">first set subset of second?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#__len">__len ()</a></td>
+ <td class="summary">cardinality of set (5.2).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#__eq">__eq (s1, s2)</a></td>
+ <td class="summary">equality between sets.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "Set"></a>
+ <strong>Set (t)</strong>
+ </dt>
+ <dd>
+ create a set. <br>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ may be a Set, Map or list-like table.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "values"></a>
+ <strong>values (self)</strong>
+ </dt>
+ <dd>
+ get a list of the values in a set.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">self</span>
+ a Set
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "map"></a>
+ <strong>map (self, fn, ...)</strong>
+ </dt>
+ <dd>
+ map a function over the values of a set.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">self</span>
+ a Set
+ </li>
+ <li><span class="parameter">fn</span>
+ a function
+ </li>
+ <li><span class="parameter">...</span>
+ extra arguments to pass to the function.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new set
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "union"></a>
+ <strong>union (self, set)</strong>
+ </dt>
+ <dd>
+ union of two sets (also +).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">self</span>
+ a Set
+ </li>
+ <li><span class="parameter">set</span>
+ another set
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new set
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "intersection"></a>
+ <strong>intersection (self, set)</strong>
+ </dt>
+ <dd>
+ intersection of two sets (also *).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">self</span>
+ a Set
+ </li>
+ <li><span class="parameter">set</span>
+ another set
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new set
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">&gt; s = Set{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}
+&gt; t = Set{<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>}
+&gt; = t
+[<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>]
+&gt; = Set.intersection(s,t)
+[<span class="number">30</span>,<span class="number">20</span>]
+&gt; = s*t
+[<span class="number">30</span>,<span class="number">20</span>]</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "difference"></a>
+ <strong>difference (self, set)</strong>
+ </dt>
+ <dd>
+ new set with elements in the set that are not in the other (also -).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">self</span>
+ a Set
+ </li>
+ <li><span class="parameter">set</span>
+ another set
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new set
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "issubset"></a>
+ <strong>issubset (self, set)</strong>
+ </dt>
+ <dd>
+ is the first set a subset of the second (also &lt;)?.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">self</span>
+ a Set
+ </li>
+ <li><span class="parameter">set</span>
+ another set
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or false
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isempty"></a>
+ <strong>isempty (self)</strong>
+ </dt>
+ <dd>
+ is the set empty?.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">self</span>
+ a Set
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or false
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isdisjoint"></a>
+ <strong>isdisjoint (s1, s2)</strong>
+ </dt>
+ <dd>
+ are the sets disjoint? (no elements in common).
+ Uses naive definition, i.e. that intersection is empty
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s1</span>
+ a Set
+ </li>
+ <li><span class="parameter">s2</span>
+ another set
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or false
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "len"></a>
+ <strong>len (s)</strong>
+ </dt>
+ <dd>
+ size of this set (also # for 5.2).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ a Set
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ size
+ </ol>
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="metamethods"></a>metamethods</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "__tostring"></a>
+ <strong>__tostring ()</strong>
+ </dt>
+ <dd>
+ string representation of a set.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "__add"></a>
+ <strong>__add ()</strong>
+ </dt>
+ <dd>
+ union of sets.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "__mul"></a>
+ <strong>__mul ()</strong>
+ </dt>
+ <dd>
+ intersection of sets.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "__sub"></a>
+ <strong>__sub ()</strong>
+ </dt>
+ <dd>
+ difference of sets.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "__pow"></a>
+ <strong>__pow ()</strong>
+ </dt>
+ <dd>
+ symmetric difference of sets.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "__lt"></a>
+ <strong>__lt ()</strong>
+ </dt>
+ <dd>
+ first set subset of second?
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "__len"></a>
+ <strong>__len ()</strong>
+ </dt>
+ <dd>
+ cardinality of set (5.2).
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "__eq"></a>
+ <strong>__eq (s1, s2)</strong>
+ </dt>
+ <dd>
+ equality between sets.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s1</span>
+
+ </li>
+ <li><span class="parameter">s2</span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.app.html b/docs/libraries/pl.app.html
new file mode 100644
index 0000000..fd69387
--- /dev/null
+++ b/docs/libraries/pl.app.html
@@ -0,0 +1,310 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><strong>pl.app</strong></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.app</code></h1>
+<p>Application support functions.</p>
+<p> See <a href="../manual/01-introduction.md.html#Application_Support">the Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.path.html#">pl.path</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#require_here">require_here (base)</a></td>
+ <td class="summary">add the current script&rsquo;s path to the Lua module path.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#appfile">appfile (file)</a></td>
+ <td class="summary">return a suitable path for files private to this application.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#platform">platform ()</a></td>
+ <td class="summary">return string indicating operating system.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#lua">lua ()</a></td>
+ <td class="summary">return the full command-line used to invoke this script.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#parse_args">parse_args (args, flags_with_values)</a></td>
+ <td class="summary">parse command-line arguments into flags and parameters.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "require_here"></a>
+ <strong>require_here (base)</strong>
+ </dt>
+ <dd>
+ add the current script&rsquo;s path to the Lua module path.
+ Applies to both the source and the binary module paths. It makes it easy for
+ the main file of a multi-file program to access its modules in the same directory.
+ <code>base</code> allows these modules to be put in a specified subdirectory, to allow for
+ cleaner deployment and resolve potential conflicts between a script name and its
+ library directory.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">base</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ optional base directory.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the current script&rsquo;s path with a trailing slash
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "appfile"></a>
+ <strong>appfile (file)</strong>
+ </dt>
+ <dd>
+ return a suitable path for files private to this application.
+ These will look like &lsquo;~/.SNAME/file&rsquo;, with &lsquo;~&rsquo; as with expanduser and
+ SNAME is the name of the script without .lua extension.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">file</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a filename (w/out path)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ a full pathname, or nil</li>
+ <li>
+ &lsquo;cannot create&rsquo; error</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "platform"></a>
+ <strong>platform ()</strong>
+ </dt>
+ <dd>
+ return string indicating operating system.
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ &lsquo;Windows&rsquo;,&lsquo;OSX&rsquo; or whatever uname returns (e.g. &lsquo;Linux&rsquo;)
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "lua"></a>
+ <strong>lua ()</strong>
+ </dt>
+ <dd>
+ return the full command-line used to invoke this script.
+ Any extra flags occupy slots, so that <code>lua -lpl</code> gives us <code>{[-2]=&apos;lua&apos;,[-1]=&apos;-lpl&apos;}</code>
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ command-line</li>
+ <li>
+ name of Lua program used</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "parse_args"></a>
+ <strong>parse_args (args, flags_with_values)</strong>
+ </dt>
+ <dd>
+ parse command-line arguments into flags and parameters.
+ Understands GNU-style command-line flags; short (<code>-f</code>) and long (<code>&ndash;flag</code>).
+ These may be given a value with either &lsquo;=&rsquo; or &lsquo;:&rsquo; (<code>-k:2</code>,<code>&ndash;alpha=3.2</code>,<code>-n2</code>);
+ note that a number value can be given without a space.
+ Multiple short args can be combined like so: ( <code>-abcd</code>).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">args</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">{string}</a></span>
+ an array of strings (default is the global <code>arg</code>)
+ </li>
+ <li><span class="parameter">flags_with_values</span>
+ <span class="types"><span class="type">tab</span></span>
+ any flags that take values, e.g. <code>{out=true}</code>
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ a table of flags (flag=value pairs)</li>
+ <li>
+ an array of parameters</li>
+ </ol>
+
+ <h3>Raises:</h3>
+ if args is nil, then the global <code>args</code> must be available!
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.array2d.html b/docs/libraries/pl.array2d.html
new file mode 100644
index 0000000..a15b347
--- /dev/null
+++ b/docs/libraries/pl.array2d.html
@@ -0,0 +1,1151 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><strong>pl.array2d</strong></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.array2d</code></h1>
+<p>Operations on two-dimensional arrays.</p>
+<p> See <a href="../manual/02-arrays.md.html#Operations_on_two_dimensional_tables">The Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.tablex.html#">pl.tablex</a>, <a href="../libraries/pl.types.html#">pl.types</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#size">size (t)</a></td>
+ <td class="summary">return the row and column size.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#column">column (a, key)</a></td>
+ <td class="summary">extract a column from the 2D array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#map">map (f, a, arg)</a></td>
+ <td class="summary">map a function over a 2D array</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#reduce_rows">reduce_rows (f, a)</a></td>
+ <td class="summary">reduce the rows using a function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#reduce_cols">reduce_cols (f, a)</a></td>
+ <td class="summary">reduce the columns using a function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#reduce2">reduce2 (opc, opr, a)</a></td>
+ <td class="summary">reduce a 2D array into a scalar, using two operations.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#map2">map2 (f, ad, bd, a, b, arg)</a></td>
+ <td class="summary">map a function over two arrays.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#product">product (f, t1, t2)</a></td>
+ <td class="summary">cartesian product of two 1d arrays.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#flatten">flatten (t)</a></td>
+ <td class="summary">flatten a 2D array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#reshape">reshape (t, nrows, co)</a></td>
+ <td class="summary">reshape a 2D array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#swap_rows">swap_rows (t, i1, i2)</a></td>
+ <td class="summary">swap two rows of an array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#swap_cols">swap_cols (t, j1, j2)</a></td>
+ <td class="summary">swap two columns of an array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#extract_rows">extract_rows (t, ridx)</a></td>
+ <td class="summary">extract the specified rows.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#extract_cols">extract_cols (t, cidx)</a></td>
+ <td class="summary">extract the specified columns.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#remove_row">remove_row (t, i)</a></td>
+ <td class="summary">remove a row from an array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#remove_col">remove_col (t, j)</a></td>
+ <td class="summary">remove a column from an array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#parse_range">parse_range (s)</a></td>
+ <td class="summary">parse a spreadsheet range.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#range">range (t, rstr)</a></td>
+ <td class="summary">get a slice of a 2D array using spreadsheet range notation.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#slice">slice (t, i1, j1, i2, j2)</a></td>
+ <td class="summary">get a slice of a 2D array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#set">set (t, value, i1, j1, i2, j2)</a></td>
+ <td class="summary">set a specified range of an array to a value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#write">write (t, f, fmt, i1, j1, i2, j2)</a></td>
+ <td class="summary">write a 2D array to a file.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#forall">forall (t, row_op, end_row_op, i1, j1, i2, j2)</a></td>
+ <td class="summary">perform an operation for all values in a 2D array.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#move">move (dest, di, dj, src, i1, j1, i2, j2)</a></td>
+ <td class="summary">move a block from the destination to the source.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#iter">iter (a, indices, i1, j1, i2, j2)</a></td>
+ <td class="summary">iterate over all elements in a 2D array, with optional indices.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#columns">columns (a)</a></td>
+ <td class="summary">iterate over all columns.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#new">new (rows, cols, val)</a></td>
+ <td class="summary">new array of specified dimensions</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "size"></a>
+ <strong>size (t)</strong>
+ </dt>
+ <dd>
+ return the row and column size.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2d array
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ <span class="types"><span class="type">int</span></span>
+ number of rows</li>
+ <li>
+ <span class="types"><span class="type">int</span></span>
+ number of cols</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "column"></a>
+ <strong>column (a, key)</strong>
+ </dt>
+ <dd>
+ extract a column from the 2D array.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ <span class="types"><span class="type">array</span></span>
+ 2d array
+ </li>
+ <li><span class="parameter">key</span>
+ an index or key
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ 1d array
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "map"></a>
+ <strong>map (f, a, arg)</strong>
+ </dt>
+ <dd>
+ map a function over a 2D array
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least one argument
+ </li>
+ <li><span class="parameter">a</span>
+ <span class="types"><span class="type">array</span></span>
+ 2d array
+ </li>
+ <li><span class="parameter">arg</span>
+ an optional extra argument to be passed to the function.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ 2d array
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "reduce_rows"></a>
+ <strong>reduce_rows (f, a)</strong>
+ </dt>
+ <dd>
+ reduce the rows using a function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ <span class="types"><span class="type">func</span></span>
+ a binary function
+ </li>
+ <li><span class="parameter">a</span>
+ <span class="types"><span class="type">array</span></span>
+ 2d array
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ 1d array
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#reduce">pl.tablex.reduce</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "reduce_cols"></a>
+ <strong>reduce_cols (f, a)</strong>
+ </dt>
+ <dd>
+ reduce the columns using a function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ <span class="types"><span class="type">func</span></span>
+ a binary function
+ </li>
+ <li><span class="parameter">a</span>
+ <span class="types"><span class="type">array</span></span>
+ 2d array
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ 1d array
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#reduce">pl.tablex.reduce</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "reduce2"></a>
+ <strong>reduce2 (opc, opr, a)</strong>
+ </dt>
+ <dd>
+ reduce a 2D array into a scalar, using two operations.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">opc</span>
+ <span class="types"><span class="type">func</span></span>
+ operation to reduce the final result
+ </li>
+ <li><span class="parameter">opr</span>
+ <span class="types"><span class="type">func</span></span>
+ operation to reduce the rows
+ </li>
+ <li><span class="parameter">a</span>
+ 2D array
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "map2"></a>
+ <strong>map2 (f, ad, bd, a, b, arg)</strong>
+ </dt>
+ <dd>
+ map a function over two arrays.
+ They can be both or either 2D arrays
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ <span class="types"><span class="type">func</span></span>
+ function of at least two arguments
+ </li>
+ <li><span class="parameter">ad</span>
+ <span class="types"><span class="type">int</span></span>
+ order of first array (1 or 2)
+ </li>
+ <li><span class="parameter">bd</span>
+ <span class="types"><span class="type">int</span></span>
+ order of second array (1 or 2)
+ </li>
+ <li><span class="parameter">a</span>
+ <span class="types"><span class="type">tab</span></span>
+ 1d or 2d array
+ </li>
+ <li><span class="parameter">b</span>
+ <span class="types"><span class="type">tab</span></span>
+ 1d or 2d array
+ </li>
+ <li><span class="parameter">arg</span>
+ optional extra argument to pass to function
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ 2D array, unless both arrays are 1D
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "product"></a>
+ <strong>product (f, t1, t2)</strong>
+ </dt>
+ <dd>
+ cartesian product of two 1d arrays.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of 2 arguments
+ </li>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">array</span></span>
+ a 1d table
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">array</span></span>
+ a 1d table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ 2d table
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">product(<span class="string">'..'</span>,{<span class="number">1</span>,<span class="number">2</span>},{<span class="string">'a'</span>,<span class="string">'b'</span>}) == {{<span class="string">'1a'</span>,<span class="string">'2a'</span>},{<span class="string">'1b'</span>,<span class="string">'2b'</span>}}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "flatten"></a>
+ <strong>flatten (t)</strong>
+ </dt>
+ <dd>
+ flatten a 2D array.
+ (this goes over columns first.)
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ 2d table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a 1d table
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">flatten {{<span class="number">1</span>,<span class="number">2</span>},{<span class="number">3</span>,<span class="number">4</span>},{<span class="number">5</span>,<span class="number">6</span>}} == {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "reshape"></a>
+ <strong>reshape (t, nrows, co)</strong>
+ </dt>
+ <dd>
+ reshape a 2D array.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ 2d array
+ </li>
+ <li><span class="parameter">nrows</span>
+ <span class="types"><span class="type">int</span></span>
+ new number of rows
+ </li>
+ <li><span class="parameter">co</span>
+ <span class="types"><span class="type">bool</span></span>
+ column-order (Fortran-style) (default false)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new 2d array
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "swap_rows"></a>
+ <strong>swap_rows (t, i1, i2)</strong>
+ </dt>
+ <dd>
+ swap two rows of an array.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2d array
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ a row index
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ a row index
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "swap_cols"></a>
+ <strong>swap_cols (t, j1, j2)</strong>
+ </dt>
+ <dd>
+ swap two columns of an array.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2d array
+ </li>
+ <li><span class="parameter">j1</span>
+ <span class="types"><span class="type">int</span></span>
+ a column index
+ </li>
+ <li><span class="parameter">j2</span>
+ <span class="types"><span class="type">int</span></span>
+ a column index
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "extract_rows"></a>
+ <strong>extract_rows (t, ridx)</strong>
+ </dt>
+ <dd>
+ extract the specified rows.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ 2d array
+ </li>
+ <li><span class="parameter">ridx</span>
+ <span class="types"><span class="type">{int}</span></span>
+ a table of row indices
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "extract_cols"></a>
+ <strong>extract_cols (t, cidx)</strong>
+ </dt>
+ <dd>
+ extract the specified columns.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ 2d array
+ </li>
+ <li><span class="parameter">cidx</span>
+ <span class="types"><span class="type">{int}</span></span>
+ a table of column indices
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "remove_row"></a>
+ <strong>remove_row (t, i)</strong>
+ </dt>
+ <dd>
+ remove a row from an array.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2d array
+ </li>
+ <li><span class="parameter">i</span>
+ <span class="types"><span class="type">int</span></span>
+ a row index
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "remove_col"></a>
+ <strong>remove_col (t, j)</strong>
+ </dt>
+ <dd>
+ remove a column from an array.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2d array
+ </li>
+ <li><span class="parameter">j</span>
+ <span class="types"><span class="type">int</span></span>
+ a column index
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "parse_range"></a>
+ <strong>parse_range (s)</strong>
+ </dt>
+ <dd>
+ parse a spreadsheet range.
+ The range can be specified either as &lsquo;A1:B2&rsquo; or &lsquo;R1C1:R2C2&rsquo;;
+ a special case is a single element (e.g &lsquo;A1&rsquo; or &lsquo;R1C1&rsquo;)
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a range.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ <span class="types"><span class="type">int</span></span>
+ start col</li>
+ <li>
+ <span class="types"><span class="type">int</span></span>
+ start row</li>
+ <li>
+ <span class="types"><span class="type">int</span></span>
+ end col</li>
+ <li>
+ <span class="types"><span class="type">int</span></span>
+ end row</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "range"></a>
+ <strong>range (t, rstr)</strong>
+ </dt>
+ <dd>
+ get a slice of a 2D array using spreadsheet range notation. @see parse_range
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2D array
+ </li>
+ <li><span class="parameter">rstr</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ range expression
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a slice
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <li><a href="../libraries/pl.array2d.html#parse_range">array2d.parse_range</a></li>
+ <li><a href="../libraries/pl.array2d.html#slice">array2d.slice</a></li>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "slice"></a>
+ <strong>slice (t, i1, j1, i2, j2)</strong>
+ </dt>
+ <dd>
+ get a slice of a 2D array. Note that if the specified range has
+ a 1D result, the rank of the result will be 1.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2D array
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start row (default 1)
+ </li>
+ <li><span class="parameter">j1</span>
+ <span class="types"><span class="type">int</span></span>
+ start col (default 1)
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end row (default N)
+ </li>
+ <li><span class="parameter">j2</span>
+ <span class="types"><span class="type">int</span></span>
+ end col (default M)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an array, 2D in general but 1D in special cases.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "set"></a>
+ <strong>set (t, value, i1, j1, i2, j2)</strong>
+ </dt>
+ <dd>
+ set a specified range of an array to a value.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2D array
+ </li>
+ <li><span class="parameter">value</span>
+ the value (may be a function)
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start row (default 1)
+ </li>
+ <li><span class="parameter">j1</span>
+ <span class="types"><span class="type">int</span></span>
+ start col (default 1)
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end row (default N)
+ </li>
+ <li><span class="parameter">j2</span>
+ <span class="types"><span class="type">int</span></span>
+ end col (default M)
+ </li>
+ </ul>
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#set">tablex.set</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "write"></a>
+ <strong>write (t, f, fmt, i1, j1, i2, j2)</strong>
+ </dt>
+ <dd>
+ write a 2D array to a file.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2D array
+ </li>
+ <li><span class="parameter">f</span>
+ a file object (default stdout)
+ </li>
+ <li><span class="parameter">fmt</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a format string (default is just to use tostring)
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start row (default 1)
+ </li>
+ <li><span class="parameter">j1</span>
+ <span class="types"><span class="type">int</span></span>
+ start col (default 1)
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end row (default N)
+ </li>
+ <li><span class="parameter">j2</span>
+ <span class="types"><span class="type">int</span></span>
+ end col (default M)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "forall"></a>
+ <strong>forall (t, row_op, end_row_op, i1, j1, i2, j2)</strong>
+ </dt>
+ <dd>
+ perform an operation for all values in a 2D array.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ 2D array
+ </li>
+ <li><span class="parameter">row_op</span>
+ <span class="types"><span class="type">func</span></span>
+ function to call on each value
+ </li>
+ <li><span class="parameter">end_row_op</span>
+ <span class="types"><span class="type">func</span></span>
+ function to call at end of each row
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start row (default 1)
+ </li>
+ <li><span class="parameter">j1</span>
+ <span class="types"><span class="type">int</span></span>
+ start col (default 1)
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end row (default N)
+ </li>
+ <li><span class="parameter">j2</span>
+ <span class="types"><span class="type">int</span></span>
+ end col (default M)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "move"></a>
+ <strong>move (dest, di, dj, src, i1, j1, i2, j2)</strong>
+ </dt>
+ <dd>
+ move a block from the destination to the source.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">dest</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2D array
+ </li>
+ <li><span class="parameter">di</span>
+ <span class="types"><span class="type">int</span></span>
+ start row in dest
+ </li>
+ <li><span class="parameter">dj</span>
+ <span class="types"><span class="type">int</span></span>
+ start col in dest
+ </li>
+ <li><span class="parameter">src</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2D array
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start row (default 1)
+ </li>
+ <li><span class="parameter">j1</span>
+ <span class="types"><span class="type">int</span></span>
+ start col (default 1)
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end row (default N)
+ </li>
+ <li><span class="parameter">j2</span>
+ <span class="types"><span class="type">int</span></span>
+ end col (default M)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "iter"></a>
+ <strong>iter (a, indices, i1, j1, i2, j2)</strong>
+ </dt>
+ <dd>
+ iterate over all elements in a 2D array, with optional indices.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ <span class="types"><span class="type">array</span></span>
+ 2D array
+ </li>
+ <li><span class="parameter">indices</span>
+ <span class="types"><span class="type">{int}</span></span>
+ with indices (default false)
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start row (default 1)
+ </li>
+ <li><span class="parameter">j1</span>
+ <span class="types"><span class="type">int</span></span>
+ start col (default 1)
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end row (default N)
+ </li>
+ <li><span class="parameter">j2</span>
+ <span class="types"><span class="type">int</span></span>
+ end col (default M)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ either value or i,j,value depending on indices
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "columns"></a>
+ <strong>columns (a)</strong>
+ </dt>
+ <dd>
+ iterate over all columns.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ <span class="types"><span class="type">array</span></span>
+ a 2D array
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ each column in turn
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "new"></a>
+ <strong>new (rows, cols, val)</strong>
+ </dt>
+ <dd>
+ new array of specified dimensions
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">rows</span>
+ <span class="types"><span class="type">int</span></span>
+ number of rows
+ </li>
+ <li><span class="parameter">cols</span>
+ <span class="types"><span class="type">int</span></span>
+ number of cols
+ </li>
+ <li><span class="parameter">val</span>
+ initial value; if it&rsquo;s a function then use <code>val(i,j)</code>
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ new 2d array
+ </ol>
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.class.html b/docs/libraries/pl.class.html
new file mode 100644
index 0000000..ff594f3
--- /dev/null
+++ b/docs/libraries/pl.class.html
@@ -0,0 +1,333 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><strong>pl.class</strong></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.class</code></h1>
+<p>Provides a reuseable and convenient framework for creating classes in Lua.</p>
+<p> Two possible notations:</p>
+
+<pre>
+B = class(A)
+class.B(A)
+</pre>
+
+
+<p> The latter form creates a named class within the current environment. Note
+ that this implicitly brings in <a href="../libraries/pl.utils.html#">pl.utils</a> as a dependency.</p>
+
+<p> See the Guide for further <a href="../manual/01-introduction.md.html#Simplifying_Object_Oriented_Programming_in_Lua">discussion</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#_init">_init (...)</a></td>
+ <td class="summary">initializes an <strong>instance</strong> upon creation.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#instance:is_a">instance:is_a (some_class)</a></td>
+ <td class="summary">checks whether an <strong>instance</strong> is derived from some class.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#some_class:class_of">some_class:class_of (some_instance)</a></td>
+ <td class="summary">checks whether an <strong>instance</strong> is derived from some class.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#some_class:cast">some_class:cast (some_instance)</a></td>
+ <td class="summary">cast an object to another class.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#class">class (base, c_arg, c)</a></td>
+ <td class="summary">create a new class, derived from a given base class.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "_init"></a>
+ <strong>_init (...)</strong>
+ </dt>
+ <dd>
+ initializes an <strong>instance</strong> upon creation.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">...</span>
+ parameters passed to the constructor
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">local</span> Cat = class()
+<span class="keyword">function</span> Cat:_init(name)
+ <span class="comment">--self:super(name) -- call the ancestor initializer if needed
+</span> self.name = name
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> pussycat = Cat(<span class="string">"pussycat"</span>)
+<span class="global">print</span>(pussycat.name) <span class="comment">--&gt; pussycat</span></pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "instance:is_a"></a>
+ <strong>instance:is_a (some_class)</strong>
+ </dt>
+ <dd>
+ checks whether an <strong>instance</strong> is derived from some class.
+ Works the other way around as <a href="../libraries/pl.class.html#some_class:class_of">class_of</a>. It has two ways of using;
+ 1) call with a class to check against, 2) call without params.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">some_class</span>
+ class to check against, or <code>nil</code> to return the class
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <code>true</code> if <code>instance</code> is derived from <code>some_class</code>, or if <code>some_class == nil</code> then
+ it returns the class table of the instance
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">local</span> pussycat = Lion() <span class="comment">-- assuming Lion derives from Cat
+</span><span class="keyword">if</span> pussycat:is_a(Cat) <span class="keyword">then</span>
+ <span class="comment">-- it's true, it is a Lion, but also a Cat
+</span><span class="keyword">end</span>
+
+<span class="keyword">if</span> pussycat:is_a() == Lion <span class="keyword">then</span>
+ <span class="comment">-- It's true
+</span><span class="keyword">end</span></pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "some_class:class_of"></a>
+ <strong>some_class:class_of (some_instance)</strong>
+ </dt>
+ <dd>
+ checks whether an <strong>instance</strong> is derived from some class.
+ Works the other way around as <a href="../libraries/pl.class.html#instance:is_a">is_a</a>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">some_instance</span>
+ instance to check against
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <code>true</code> if <code>some_instance</code> is derived from <code>some_class</code>
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">local</span> pussycat = Lion() <span class="comment">-- assuming Lion derives from Cat
+</span><span class="keyword">if</span> Cat:class_of(pussycat) <span class="keyword">then</span>
+ <span class="comment">-- it's true
+</span><span class="keyword">end</span></pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "some_class:cast"></a>
+ <strong>some_class:cast (some_instance)</strong>
+ </dt>
+ <dd>
+ cast an object to another class.
+ It is not clever (or safe!) so use carefully.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">some_instance</span>
+ the object to be changed
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "class"></a>
+ <strong>class (base, c_arg, c)</strong>
+ </dt>
+ <dd>
+ create a new class, derived from a given base class.
+ Supporting two class creation syntaxes:
+ either <code>Name = class(base)</code> or <code>class.Name(base)</code>.
+ The first form returns the class directly and does not set its <code>_name</code>.
+ The second form creates a variable <code>Name</code> in the current environment set
+ to the class, and also sets <code>_name</code>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">base</span>
+ optional base class
+ </li>
+ <li><span class="parameter">c_arg</span>
+ optional parameter to class constructor
+ </li>
+ <li><span class="parameter">c</span>
+ optional table to be used as class
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.compat.html b/docs/libraries/pl.compat.html
new file mode 100644
index 0000000..cc9bd0c
--- /dev/null
+++ b/docs/libraries/pl.compat.html
@@ -0,0 +1,372 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+<li><a href="#Lua_5_2_Functions_Available_for_5_1">Lua 5.2 Functions Available for 5.1 </a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><strong>pl.compat</strong></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.compat</code></h1>
+<p>Lua 5.1/5.2/5.3 compatibility.</p>
+<p> Ensures that <a href="../libraries/pl.compat.html#table.pack">table.pack</a> and <a href="../libraries/pl.compat.html#package.searchpath">package.searchpath</a> are available
+ for Lua 5.1 and LuaJIT.
+ The exported function <a href="../libraries/pl.compat.html#load">load</a> is Lua 5.2 compatible.
+ <a href="../libraries/pl.compat.html#setfenv">compat.setfenv</a> and <a href="../libraries/pl.compat.html#getfenv">compat.getfenv</a> are available for Lua 5.2, although
+ they are not always guaranteed to work.</p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#execute">execute (cmd)</a></td>
+ <td class="summary">execute a shell command.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#load">load (ld[, source[, mode[, env]]])</a></td>
+ <td class="summary">Load Lua code as a text or binary chunk.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getfenv">getfenv (f)</a></td>
+ <td class="summary">Get environment of a function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#setfenv">setfenv (f, env)</a></td>
+ <td class="summary">Set environment of a function</td>
+ </tr>
+</table>
+<h2><a href="#Lua_5_2_Functions_Available_for_5_1">Lua 5.2 Functions Available for 5.1 </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#table.pack">table.pack (...)</a></td>
+ <td class="summary">pack an argument list into a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#t">t</a></td>
+ <td class="summary">unpack a table and return the elements.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#package.searchpath">package.searchpath (mod, path)</a></td>
+ <td class="summary">return the full path where a Lua module name would be matched.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "execute"></a>
+ <strong>execute (cmd)</strong>
+ </dt>
+ <dd>
+ execute a shell command.
+ This is a compatibility function that returns the same for Lua 5.1 and Lua 5.2
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">cmd</span>
+ a shell command
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ true if successful</li>
+ <li>
+ actual return code</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "load"></a>
+ <strong>load (ld[, source[, mode[, env]]])</strong>
+ </dt>
+ <dd>
+ Load Lua code as a text or binary chunk.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">ld</span>
+ code string or loader
+ </li>
+ <li><span class="parameter">source</span>
+ name of chunk for errors
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">mode</span>
+ &lsquo;b&rsquo;, &rsquo;t' or &lsquo;bt&rsquo;
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">env</span>
+ environment to load the chunk in
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "getfenv"></a>
+ <strong>getfenv (f)</strong>
+ </dt>
+ <dd>
+ Get environment of a function.
+ With Lua 5.2, may return nil for a function with no global references!
+ Based on code by <a href="http://lua-users.org/lists/lua-l/2010-06/msg00313.html">Sergey Rozhenko</a>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function or a call stack reference
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "setfenv"></a>
+ <strong>setfenv (f, env)</strong>
+ </dt>
+ <dd>
+ Set environment of a function
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function or a call stack reference
+ </li>
+ <li><span class="parameter">env</span>
+ a table that becomes the new environment of <code>f</code>
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Lua_5_2_Functions_Available_for_5_1"></a>Lua 5.2 Functions Available for 5.1 </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "table.pack"></a>
+ <strong>table.pack (...)</strong>
+ </dt>
+ <dd>
+ pack an argument list into a table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">...</span>
+ any arguments
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table with field n set to the length
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "t"></a>
+ <strong>t</strong>
+ </dt>
+ <dd>
+ unpack a table and return the elements.
+
+
+ <ul>
+ <li><span class="parameter">t</span>
+ index of the last element to unpack, defaults to #t
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">i</span>
+ index from which to start unpacking, defaults to 1
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">t</span>
+ index of the last element to unpack, defaults to #t
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "package.searchpath"></a>
+ <strong>package.searchpath (mod, path)</strong>
+ </dt>
+ <dd>
+ return the full path where a Lua module name would be matched.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">mod</span>
+ module name, possibly dotted
+ </li>
+ <li><span class="parameter">path</span>
+ a path in the same form as package.path or package.cpath
+ </li>
+ </ul>
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.path.html#package_path">path.package_path</a>
+ </ul>
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.comprehension.html b/docs/libraries/pl.comprehension.html
new file mode 100644
index 0000000..b552ee7
--- /dev/null
+++ b/docs/libraries/pl.comprehension.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><strong>pl.comprehension</strong></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.comprehension</code></h1>
+<p>List comprehensions implemented in Lua.</p>
+<p> See the <a href="http://lua-users.org/wiki/ListComprehensions">wiki page</a></p>
+
+<pre>
+<span class="keyword">local</span> C= <span class="global">require</span> <span class="string">'pl.comprehension'</span> . new()
+
+C (<span class="string">'x for x=1,10'</span>) ()
+==&gt; {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>,<span class="number">10</span>}
+C <span class="string">'x^2 for x=1,4'</span> ()
+==&gt; {<span class="number">1</span>,<span class="number">4</span>,<span class="number">9</span>,<span class="number">16</span>}
+C <span class="string">'{x,x^2} for x=1,4'</span> ()
+==&gt; {{<span class="number">1</span>,<span class="number">1</span>},{<span class="number">2</span>,<span class="number">4</span>},{<span class="number">3</span>,<span class="number">9</span>},{<span class="number">4</span>,<span class="number">16</span>}}
+C <span class="string">'2*x for x'</span> {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
+==&gt; {<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>}
+dbl = C <span class="string">'2*x for x'</span>
+dbl {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}
+==&gt; {<span class="number">20</span>,<span class="number">40</span>,<span class="number">60</span>}
+C <span class="string">'x for x if x % 2 == 0'</span> {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}
+==&gt; {<span class="number">2</span>,<span class="number">4</span>}
+C <span class="string">'{x,y} for x = 1,2 for y = 1,2'</span> ()
+==&gt; {{<span class="number">1</span>,<span class="number">1</span>},{<span class="number">1</span>,<span class="number">2</span>},{<span class="number">2</span>,<span class="number">1</span>},{<span class="number">2</span>,<span class="number">2</span>}}
+C <span class="string">'{x,y} for x for y'</span> ({<span class="number">1</span>,<span class="number">2</span>},{<span class="number">10</span>,<span class="number">20</span>})
+==&gt; {{<span class="number">1</span>,<span class="number">10</span>},{<span class="number">1</span>,<span class="number">20</span>},{<span class="number">2</span>,<span class="number">10</span>},{<span class="number">2</span>,<span class="number">20</span>}}
+<span class="global">assert</span>(C <span class="string">'sum(x^2 for x)'</span> {<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>} == <span class="number">2</span>^<span class="number">2</span>+<span class="number">3</span>^<span class="number">2</span>+<span class="number">4</span>^<span class="number">2</span>)
+</pre>
+
+
+<p> &copy; 2008 David Manura. Licensed under the same terms as Lua (MIT license).</p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.luabalanced.html#">pl.luabalanced</a></p>
+
+<p> See <a href="../manual/07-functional.md.html#List_Comprehensions">the Guide</a></p>
+
+
+
+<br/>
+<br/>
+
+
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.config.html b/docs/libraries/pl.config.html
new file mode 100644
index 0000000..e1331a6
--- /dev/null
+++ b/docs/libraries/pl.config.html
@@ -0,0 +1,254 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><strong>pl.config</strong></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.config</code></h1>
+<p>Reads configuration files into a Lua table.</p>
+<p><p> Understands INI files, classic Unix config files, and simple
+ delimited columns of values. See <a href="../manual/06-data.md.html#Reading_Configuration_Files">the Guide</a></p>
+
+<pre>
+# test.config
+# Read timeout <span class="keyword">in</span> seconds
+read.timeout=<span class="number">10</span>
+# Write timeout <span class="keyword">in</span> seconds
+write.timeout=<span class="number">5</span>
+#acceptable ports
+ports = <span class="number">1002</span>,<span class="number">1003</span>,<span class="number">1004</span>
+
+<span class="comment">-- readconfig.lua
+</span><span class="keyword">local</span> config = <span class="global">require</span> <span class="string">'config'</span>
+<span class="keyword">local</span> t = config.read <span class="string">'test.config'</span>
+<span class="global">print</span>(pretty.write(t))
+
+### output #####
+{
+ ports = {
+ <span class="number">1002</span>,
+ <span class="number">1003</span>,
+ <span class="number">1004</span>
+ },
+ write_timeout = <span class="number">5</span>,
+ read_timeout = <span class="number">10</span>
+}
+</pre>
+</p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#lines">lines (file)</a></td>
+ <td class="summary">like io.lines(), but allows for lines to be continued with &lsquo;\&rsquo;.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#read">read (file[, cnfg])</a></td>
+ <td class="summary">read a configuration file into a table</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "lines"></a>
+ <strong>lines (file)</strong>
+ </dt>
+ <dd>
+ like io.lines(), but allows for lines to be continued with &lsquo;\&rsquo;.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">file</span>
+ a file-like object (anything where read() returns the next line) or a filename.
+ Defaults to stardard input.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ an iterator over the lines, or nil</li>
+ <li>
+ error &lsquo;not a file-like object&rsquo; or &lsquo;file is nil&rsquo;</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "read"></a>
+ <strong>read (file[, cnfg])</strong>
+ </dt>
+ <dd>
+ read a configuration file into a table
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">file</span>
+ either a file-like object or a string, which must be a filename
+ </li>
+ <li><span class="parameter">cnfg</span>
+ <span class="types"><span class="type">tab</span></span>
+ <p> a configuration table that may contain these fields:</p>
+
+<ul>
+<li><code>smart</code> try to deduce what kind of config file we have (default false)</li>
+<li><code>variablilize</code> make names into valid Lua identifiers (default true)</li>
+<li><code>convert_numbers</code> try to convert values into numbers (default true)</li>
+<li><code>trim_space</code> ensure that there is no starting or trailing whitespace with values (default true)</li>
+<li><code>trim_quotes</code> remove quotes from strings (default false)</li>
+<li><code>list_delim</code> delimiter to use when separating columns (default &lsquo;,&rsquo;)</li>
+<li><code>keysep</code> separator between key and value pairs (default &lsquo;=&rsquo;)</li>
+</ul>
+
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ a table containing items, or <code>nil</code></li>
+ <li>
+ error message (same as <a href="../libraries/pl.config.html#lines">config.lines</a></li>
+ </ol>
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.data.html b/docs/libraries/pl.data.html
new file mode 100644
index 0000000..0d6dddb
--- /dev/null
+++ b/docs/libraries/pl.data.html
@@ -0,0 +1,570 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><strong>pl.data</strong></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.data</code></h1>
+<p>Reading and querying simple tabular data.</p>
+<p>
+
+<pre>
+data.read <span class="string">'test.txt'</span>
+==&gt; {{<span class="number">10</span>,<span class="number">20</span>},{<span class="number">2</span>,<span class="number">5</span>},{<span class="number">40</span>,<span class="number">50</span>},fieldnames={<span class="string">'x'</span>,<span class="string">'y'</span>},delim=<span class="string">','</span>}
+</pre>
+
+
+<p> Provides a way of creating basic SQL-like queries.</p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+<span class="keyword">local</span> d = data.read(<span class="string">'xyz.txt'</span>)
+<span class="keyword">local</span> q = d:<span class="global">select</span>(<span class="string">'x,y,z where x &gt; 3 and z &lt; 2 sort by y'</span>)
+<span class="keyword">for</span> x,y,z <span class="keyword">in</span> q <span class="keyword">do</span>
+ <span class="global">print</span>(x,y,z)
+<span class="keyword">end</span>
+</pre>
+
+
+<p> See <a href="../manual/06-data.md.html#Reading_Columnar_Data">the Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.array2d.html#">pl.array2d</a> (fallback methods)</p></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#Data.column_by_name">Data.column_by_name (name)</a></td>
+ <td class="summary">return a particular column as a list of values (method).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Data.select">Data.select (condn)</a></td>
+ <td class="summary">return a query iterator on this data (method).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Data.select_row">Data.select_row (condn)</a></td>
+ <td class="summary">return a row iterator on this data (method).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Data.copy_select">Data.copy_select (condn)</a></td>
+ <td class="summary">return a new data object based on this query (method).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Data.column_names">Data.column_names ()</a></td>
+ <td class="summary">return the field names of this data object (method).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Data.write_row">Data.write_row (f)</a></td>
+ <td class="summary">write out a row (method).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Data.write">Data.write (f)</a></td>
+ <td class="summary">write data out to file (method).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#read">read (file, cnfg)</a></td>
+ <td class="summary">read a delimited file in a Lua table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#write">write (data, file[, fieldnames[, delim='\t']])</a></td>
+ <td class="summary">write 2D data to a file.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#new">new (d[, fieldnames])</a></td>
+ <td class="summary">create a new dataset from a table of rows.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#query">query (data, condn, context, return_row)</a></td>
+ <td class="summary">create a query iterator from a select string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#filter">filter (Q, infile, outfile, dont_fail)</a></td>
+ <td class="summary">Filter input using a query.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "Data.column_by_name"></a>
+ <strong>Data.column_by_name (name)</strong>
+ </dt>
+ <dd>
+ return a particular column as a list of values (method).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">name</span>
+ either name of column, or numerical index.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Data.select"></a>
+ <strong>Data.select (condn)</strong>
+ </dt>
+ <dd>
+ return a query iterator on this data (method).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">condn</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the query expression
+ </li>
+ </ul>
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.data.html#query">data.query</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "Data.select_row"></a>
+ <strong>Data.select_row (condn)</strong>
+ </dt>
+ <dd>
+ return a row iterator on this data (method).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">condn</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the query expression
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Data.copy_select"></a>
+ <strong>Data.copy_select (condn)</strong>
+ </dt>
+ <dd>
+ return a new data object based on this query (method).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">condn</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the query expression
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Data.column_names"></a>
+ <strong>Data.column_names ()</strong>
+ </dt>
+ <dd>
+ return the field names of this data object (method).
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Data.write_row"></a>
+ <strong>Data.write_row (f)</strong>
+ </dt>
+ <dd>
+ write out a row (method).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ file-like object
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Data.write"></a>
+ <strong>Data.write (f)</strong>
+ </dt>
+ <dd>
+ write data out to file (method).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ file-like object
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "read"></a>
+ <strong>read (file, cnfg)</strong>
+ </dt>
+ <dd>
+ read a delimited file in a Lua table.
+ By default, attempts to treat first line as separated list of fieldnames.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">file</span>
+ a filename or a file-like object
+ </li>
+ <li><span class="parameter">cnfg</span> parsing options
+ <ul>
+ <li><span class="parameter">delim</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string pattern to split fields
+ </li>
+ <li><span class="parameter">fieldnames</span>
+ <span class="types"><span class="type">array</span></span>
+ (i.e. don&rsquo;t read from first line)
+ </li>
+ <li><span class="parameter">no_convert</span>
+ <span class="types"><span class="type">bool</span></span>
+ (default is to try conversion on first data line)
+ </li>
+ <li><span class="parameter">convert</span>
+ <span class="types"><span class="type">tab</span></span>
+ table of custom conversion functions with column keys
+ </li>
+ <li><span class="parameter">numfields</span>
+ <span class="types"><span class="type">int</span></span>
+ indices of columns known to be numbers
+ </li>
+ <li><span class="parameter">last_field_collect</span>
+ <span class="types"><span class="type">bool</span></span>
+ only split as many fields as fieldnames.
+ </li>
+ <li><span class="parameter">thousands_dot</span>
+ <span class="types"><span class="type">int</span></span>
+ thousands separator in Excel CSV is &lsquo;.&rsquo;
+ </li>
+ <li><span class="parameter">csv</span>
+ <span class="types"><span class="type">bool</span></span>
+ fields may be double-quoted and contain commas;
+ Also, empty fields are considered to be equivalent to zero.
+ </li>
+ </li></ul>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ <a href="../libraries/pl.data.html">data</a> object, or <code>nil</code></li>
+ <li>
+ error message. May be a file error, &lsquo;not a file-like object&rsquo;
+ or a conversion error</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "write"></a>
+ <strong>write (data, file[, fieldnames[, delim='\t']])</strong>
+ </dt>
+ <dd>
+ write 2D data to a file.
+ Does not assume that the data has actually been
+ generated with <a href="../libraries/pl.data.html#new">new</a> or <a href="../libraries/pl.data.html#read">read</a>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">data</span>
+ 2D array
+ </li>
+ <li><span class="parameter">file</span>
+ filename or file-like object
+ </li>
+ <li><span class="parameter">fieldnames</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">{string}</a></span>
+ list of fields (optional)
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">delim</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ delimiter (default tab)
+ (<em>default</em> '\t')
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or nil, error
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "new"></a>
+ <strong>new (d[, fieldnames])</strong>
+ </dt>
+ <dd>
+ create a new dataset from a table of rows.
+ Can specify the fieldnames, else the table must have a field called
+ &lsquo;fieldnames&rsquo;, which is either a string of delimiter-separated names,
+ or a table of names. <br>
+ If the table does not have a field called &lsquo;delim&rsquo;, then an attempt will be
+ made to guess it from the fieldnames string, defaults otherwise to tab.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">d</span>
+ the table.
+ </li>
+ <li><span class="parameter">fieldnames</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">{string}</a></span>
+ optional fieldnames
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the table.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "query"></a>
+ <strong>query (data, condn, context, return_row)</strong>
+ </dt>
+ <dd>
+ create a query iterator from a select string.
+ Select string has this format: <br>
+ FIELDLIST [ where LUA-CONDN [ sort by FIELD] ]<br>
+ FIELDLIST is a comma-separated list of valid fields, or &lsquo;*&rsquo;. <br> <br>
+ The condition can also be a table, with fields &lsquo;fields&rsquo; (comma-sep string or
+ table), &lsquo;sort_by&rsquo; (string) and &lsquo;where&rsquo; (Lua expression string or function)
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">data</span>
+ table produced by read
+ </li>
+ <li><span class="parameter">condn</span>
+ select string or table
+ </li>
+ <li><span class="parameter">context</span>
+ a list of tables to be searched when resolving functions
+ </li>
+ <li><span class="parameter">return_row</span>
+ if true, wrap the results in a row table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ an iterator over the specified fields, or nil</li>
+ <li>
+ an error message</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "filter"></a>
+ <strong>filter (Q, infile, outfile, dont_fail)</strong>
+ </dt>
+ <dd>
+ Filter input using a query.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">Q</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a query string
+ </li>
+ <li><span class="parameter">infile</span>
+ filename or file-like object
+ </li>
+ <li><span class="parameter">outfile</span>
+ filename or file-like object
+ </li>
+ <li><span class="parameter">dont_fail</span>
+ <span class="types"><span class="type">bool</span></span>
+ true if you want to return an error, not just fail
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.dir.html b/docs/libraries/pl.dir.html
new file mode 100644
index 0000000..ffe71f6
--- /dev/null
+++ b/docs/libraries/pl.dir.html
@@ -0,0 +1,613 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><strong>pl.dir</strong></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.dir</code></h1>
+<p>Listing files in directories and creating/removing directory paths.</p>
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.path.html#">pl.path</a></p>
+
+<p> Soft Dependencies: <code>alien</code>, <code>ffi</code> (either are used on Windows for copying/moving files)</p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#fnmatch">fnmatch (filename, pattern)</a></td>
+ <td class="summary">Test whether a file name matches a shell pattern.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#filter">filter (filenames, pattern)</a></td>
+ <td class="summary">Return a list of all file names within an array which match a pattern.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getfiles">getfiles (dir, mask)</a></td>
+ <td class="summary">return a list of all files in a directory which match the a shell pattern.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getdirectories">getdirectories (dir)</a></td>
+ <td class="summary">return a list of all subdirectories of the directory.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#copyfile">copyfile (src, dest, flag)</a></td>
+ <td class="summary">copy a file.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#movefile">movefile (src, dest)</a></td>
+ <td class="summary">move a file.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#walk">walk (root, bottom_up, follow_links)</a></td>
+ <td class="summary">return an iterator which walks through a directory tree starting at root.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#rmtree">rmtree (fullpath)</a></td>
+ <td class="summary">remove a whole directory tree.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#makepath">makepath (p)</a></td>
+ <td class="summary">create a directory path.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#clonetree">clonetree (path1, path2, file_fun, verbose)</a></td>
+ <td class="summary">clone a directory tree.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#dirtree">dirtree (d)</a></td>
+ <td class="summary">return an iterator over all entries in a directory tree</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getallfiles">getallfiles (start_path, shell_pattern)</a></td>
+ <td class="summary">Recursively returns all the file starting at <em>path</em>.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "fnmatch"></a>
+ <strong>fnmatch (filename, pattern)</strong>
+ </dt>
+ <dd>
+ Test whether a file name matches a shell pattern.
+ Both parameters are case-normalized if operating system is
+ case-insensitive.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">filename</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file name.
+ </li>
+ <li><span class="parameter">pattern</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A shell pattern. The only special characters are
+ <code>&apos;<em>&apos;</code> and <code>&apos;?&apos;</code>: <code>&apos;</em>&apos;</code> matches any sequence of characters and
+ <code>&apos;?&apos;</code> matches any single character.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><span class="type">bool</span></span>
+
+ </ol>
+
+ <h3>Raises:</h3>
+ dir and mask must be strings
+
+
+
+</dd>
+ <dt>
+ <a name = "filter"></a>
+ <strong>filter (filenames, pattern)</strong>
+ </dt>
+ <dd>
+ Return a list of all file names within an array which match a pattern.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">filenames</span>
+ <span class="types"><span class="type">tab</span></span>
+ An array containing file names.
+ </li>
+ <li><span class="parameter">pattern</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A shell pattern.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="../classes/pl.List.html">List(string)</a></span>
+ List of matching file names.
+ </ol>
+
+ <h3>Raises:</h3>
+ dir and mask must be strings
+
+
+
+</dd>
+ <dt>
+ <a name = "getfiles"></a>
+ <strong>getfiles (dir, mask)</strong>
+ </dt>
+ <dd>
+ return a list of all files in a directory which match the a shell pattern.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">dir</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A directory. If not given, all files in current directory are returned.
+ </li>
+ <li><span class="parameter">mask</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A shell pattern. If not given, all files are returned.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">{string}</a></span>
+ list of files
+ </ol>
+
+ <h3>Raises:</h3>
+ dir and mask must be strings
+
+
+
+</dd>
+ <dt>
+ <a name = "getdirectories"></a>
+ <strong>getdirectories (dir)</strong>
+ </dt>
+ <dd>
+ return a list of all subdirectories of the directory.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">dir</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A directory
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">{string}</a></span>
+ a list of directories
+ </ol>
+
+ <h3>Raises:</h3>
+ dir must be a a valid directory
+
+
+
+</dd>
+ <dt>
+ <a name = "copyfile"></a>
+ <strong>copyfile (src, dest, flag)</strong>
+ </dt>
+ <dd>
+ copy a file.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">src</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ source file
+ </li>
+ <li><span class="parameter">dest</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ destination file or directory
+ </li>
+ <li><span class="parameter">flag</span>
+ <span class="types"><span class="type">bool</span></span>
+ true if you want to force the copy (default)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><span class="type">bool</span></span>
+ operation succeeded
+ </ol>
+
+ <h3>Raises:</h3>
+ src and dest must be strings
+
+
+
+</dd>
+ <dt>
+ <a name = "movefile"></a>
+ <strong>movefile (src, dest)</strong>
+ </dt>
+ <dd>
+ move a file.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">src</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ source file
+ </li>
+ <li><span class="parameter">dest</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ destination file or directory
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><span class="type">bool</span></span>
+ operation succeeded
+ </ol>
+
+ <h3>Raises:</h3>
+ src and dest must be strings
+
+
+
+</dd>
+ <dt>
+ <a name = "walk"></a>
+ <strong>walk (root, bottom_up, follow_links)</strong>
+ </dt>
+ <dd>
+ return an iterator which walks through a directory tree starting at root.
+ The iterator returns (root,dirs,files)
+ Note that dirs and files are lists of names (i.e. you must say path.join(root,d)
+ to get the actual full path)
+ If bottom_up is false (or not present), then the entries at the current level are returned
+ before we go deeper. This means that you can modify the returned list of directories before
+ continuing.
+ This is a clone of os.walk from the Python libraries.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">root</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A starting directory
+ </li>
+ <li><span class="parameter">bottom_up</span>
+ <span class="types"><span class="type">bool</span></span>
+ False if we start listing entries immediately.
+ </li>
+ <li><span class="parameter">follow_links</span>
+ <span class="types"><span class="type">bool</span></span>
+ follow symbolic links
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an iterator returning root,dirs,files
+ </ol>
+
+ <h3>Raises:</h3>
+ root must be a directory
+
+
+
+</dd>
+ <dt>
+ <a name = "rmtree"></a>
+ <strong>rmtree (fullpath)</strong>
+ </dt>
+ <dd>
+ remove a whole directory tree.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fullpath</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A directory path
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ true or nil</li>
+ <li>
+ error if failed</li>
+ </ol>
+
+ <h3>Raises:</h3>
+ fullpath must be a string
+
+
+
+</dd>
+ <dt>
+ <a name = "makepath"></a>
+ <strong>makepath (p)</strong>
+ </dt>
+ <dd>
+ create a directory path.
+ This will create subdirectories as necessary!
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">p</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A directory path
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true on success, nil + errormsg on failure
+ </ol>
+
+ <h3>Raises:</h3>
+ failure to create
+
+
+
+</dd>
+ <dt>
+ <a name = "clonetree"></a>
+ <strong>clonetree (path1, path2, file_fun, verbose)</strong>
+ </dt>
+ <dd>
+ clone a directory tree. Will always try to create a new directory structure
+ if necessary.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">path1</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the base path of the source tree
+ </li>
+ <li><span class="parameter">path2</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the new base path for the destination
+ </li>
+ <li><span class="parameter">file_fun</span>
+ <span class="types"><span class="type">func</span></span>
+ an optional function to apply on all files
+ </li>
+ <li><span class="parameter">verbose</span>
+ <span class="types"><span class="type">bool</span></span>
+ an optional boolean to control the verbosity of the output.
+ It can also be a logging function that behaves like print()
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ true, or nil</li>
+ <li>
+ error message, or list of failed directory creations</li>
+ <li>
+ list of failed file operations</li>
+ </ol>
+
+ <h3>Raises:</h3>
+ path1 and path2 must be strings
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">clonetree(<span class="string">'.'</span>,<span class="string">'../backup'</span>,copyfile)</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "dirtree"></a>
+ <strong>dirtree (d)</strong>
+ </dt>
+ <dd>
+ return an iterator over all entries in a directory tree
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">d</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a directory
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an iterator giving pathname and mode (true for dir, false otherwise)
+ </ol>
+
+ <h3>Raises:</h3>
+ d must be a non-empty string
+
+
+
+</dd>
+ <dt>
+ <a name = "getallfiles"></a>
+ <strong>getallfiles (start_path, shell_pattern)</strong>
+ </dt>
+ <dd>
+ Recursively returns all the file starting at <em>path</em>. It can optionally take a shell pattern and
+ only returns files that match <em>shell_pattern</em>. If a pattern is given it will do a case insensitive search.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">start_path</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A directory. If not given, all files in current directory are returned.
+ </li>
+ <li><span class="parameter">shell_pattern</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A shell pattern. If not given, all files are returned.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><a class="type" href="../classes/pl.List.html">List(string)</a></span>
+ containing all the files found recursively starting at <em>path</em> and filtered by <em>shell_pattern</em>.
+ </ol>
+
+ <h3>Raises:</h3>
+ start_path must be a directory
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.file.html b/docs/libraries/pl.file.html
new file mode 100644
index 0000000..54221fd
--- /dev/null
+++ b/docs/libraries/pl.file.html
@@ -0,0 +1,378 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><strong>pl.file</strong></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.file</code></h1>
+<p>File manipulation functions: reading, writing, moving and copying.</p>
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.dir.html#">pl.dir</a>, <a href="../libraries/pl.path.html#">pl.path</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#read">read (filename)</a></td>
+ <td class="summary">return the contents of a file as a string</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#write">write (filename, str)</a></td>
+ <td class="summary">write a string to a file</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#copy">copy (src, dest, flag)</a></td>
+ <td class="summary">copy a file.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#move">move (src, dest)</a></td>
+ <td class="summary">move a file.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#access_time">access_time (path)</a></td>
+ <td class="summary">Return the time of last access as the number of seconds since the epoch.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#creation_time">creation_time (path)</a></td>
+ <td class="summary">Return when the file was created.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#modified_time">modified_time (path)</a></td>
+ <td class="summary">Return the time of last modification</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#delete">delete (path)</a></td>
+ <td class="summary">Delete a file</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "read"></a>
+ <strong>read (filename)</strong>
+ </dt>
+ <dd>
+ return the contents of a file as a string
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">filename</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ The file path
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ file contents
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "write"></a>
+ <strong>write (filename, str)</strong>
+ </dt>
+ <dd>
+ write a string to a file
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">filename</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ The file path
+ </li>
+ <li><span class="parameter">str</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ The string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "copy"></a>
+ <strong>copy (src, dest, flag)</strong>
+ </dt>
+ <dd>
+ copy a file.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">src</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ source file
+ </li>
+ <li><span class="parameter">dest</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ destination file
+ </li>
+ <li><span class="parameter">flag</span>
+ <span class="types"><span class="type">bool</span></span>
+ true if you want to force the copy (default)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true if operation succeeded
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "move"></a>
+ <strong>move (src, dest)</strong>
+ </dt>
+ <dd>
+ move a file.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">src</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ source file
+ </li>
+ <li><span class="parameter">dest</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ destination file
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true if operation succeeded, else false and the reason for the error.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "access_time"></a>
+ <strong>access_time (path)</strong>
+ </dt>
+ <dd>
+ Return the time of last access as the number of seconds since the epoch.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">path</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "creation_time"></a>
+ <strong>creation_time (path)</strong>
+ </dt>
+ <dd>
+ Return when the file was created.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">path</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "modified_time"></a>
+ <strong>modified_time (path)</strong>
+ </dt>
+ <dd>
+ Return the time of last modification
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">path</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "delete"></a>
+ <strong>delete (path)</strong>
+ </dt>
+ <dd>
+ Delete a file
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">path</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.func.html b/docs/libraries/pl.func.html
new file mode 100644
index 0000000..b4c2e2c
--- /dev/null
+++ b/docs/libraries/pl.func.html
@@ -0,0 +1,461 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><strong>pl.func</strong></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.func</code></h1>
+<p>Functional helpers like composition, binding and placeholder expressions.</p>
+<p> Placeholder expressions are useful for short anonymous functions, and were
+ inspired by the Boost Lambda library.</p>
+
+<pre>
+&gt; utils.import <span class="string">'pl.func'</span>
+&gt; ls = List{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}
+&gt; = ls:map(_1+<span class="number">1</span>)
+{<span class="number">11</span>,<span class="number">21</span>,<span class="number">31</span>}
+</pre>
+
+
+<p> They can also be used to <em>bind</em> particular arguments of a function.</p>
+
+<pre>
+&gt; p = bind(<span class="global">print</span>,<span class="string">'start&gt;'</span>,_0)
+&gt; p(<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>)
+&gt; start&gt; <span class="number">10</span> <span class="number">20</span> <span class="number">30</span>
+</pre>
+
+
+<p> See <a href="../manual/07-functional.md.html#Creating_Functions_from_Functions">the Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.tablex.html#">pl.tablex</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#import">import (tname, context)</a></td>
+ <td class="summary">wrap a table of functions.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#register">register (fun[, name])</a></td>
+ <td class="summary">register a function for use in placeholder expressions.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#tail">tail (ls)</a></td>
+ <td class="summary">all elements of a table except the first.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#repr">repr (e, lastpred)</a></td>
+ <td class="summary">create a string representation of a placeholder expression.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#instantiate">instantiate (e)</a></td>
+ <td class="summary">instantiate a PE into an actual function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#I">I (e)</a></td>
+ <td class="summary">instantiate a PE unless it has already been done.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#bind1">bind1 (fn, p)</a></td>
+ <td class="summary">bind the first parameter of the function to a value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#compose">compose (f, g)</a></td>
+ <td class="summary">create a function which chains two functions.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#bind">bind (fn, ...)</a></td>
+ <td class="summary">bind the arguments of a function to given values.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "import"></a>
+ <strong>import (tname, context)</strong>
+ </dt>
+ <dd>
+ wrap a table of functions. This makes them available for use in
+ placeholder expressions.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tname</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a table name
+ </li>
+ <li><span class="parameter">context</span>
+ <span class="types"><span class="type">tab</span></span>
+ context to put results, defaults to environment of caller
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "register"></a>
+ <strong>register (fun[, name])</strong>
+ </dt>
+ <dd>
+ register a function for use in placeholder expressions.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function
+ </li>
+ <li><span class="parameter">name</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ an optional name
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a placeholder functiond
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "tail"></a>
+ <strong>tail (ls)</strong>
+ </dt>
+ <dd>
+ all elements of a table except the first.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">ls</span>
+ <span class="types"><span class="type">tab</span></span>
+ a list-like table.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "repr"></a>
+ <strong>repr (e, lastpred)</strong>
+ </dt>
+ <dd>
+ create a string representation of a placeholder expression.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">e</span>
+ a placeholder expression
+ </li>
+ <li><span class="parameter">lastpred</span>
+ not used
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "instantiate"></a>
+ <strong>instantiate (e)</strong>
+ </dt>
+ <dd>
+ instantiate a PE into an actual function. First we find the largest placeholder used,
+ e.g. _2; from this a list of the formal parameters can be build. Then we collect and replace
+ any non-PE values from the PE, and build up a constant binding list.
+ Finally, the expression can be compiled, and e.__PE_function is set.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">e</span>
+ a placeholder expression
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "I"></a>
+ <strong>I (e)</strong>
+ </dt>
+ <dd>
+ instantiate a PE unless it has already been done.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">e</span>
+ a placeholder expression
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the function
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "bind1"></a>
+ <strong>bind1 (fn, p)</strong>
+ </dt>
+ <dd>
+ bind the first parameter of the function to a value.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fn</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of one or more arguments
+ </li>
+ <li><span class="parameter">p</span>
+ a value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function of one less argument
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">(bind1(<span class="global">math</span>.max,<span class="number">10</span>))(<span class="number">20</span>) == <span class="global">math</span>.max(<span class="number">10</span>,<span class="number">20</span>)</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "compose"></a>
+ <strong>compose (f, g)</strong>
+ </dt>
+ <dd>
+ create a function which chains two functions.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least one argument
+ </li>
+ <li><span class="parameter">g</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least one argument
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">printf = compose(<span class="global">io</span>.write,<span class="global">string</span>.format)</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "bind"></a>
+ <strong>bind (fn, ...)</strong>
+ </dt>
+ <dd>
+ bind the arguments of a function to given values.
+ <code>bind(fn,v,_2)</code> is equivalent to <code>bind1(fn,v)</code>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fn</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least one argument
+ </li>
+ <li><span class="parameter">...</span>
+ values or placeholder variables
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">(bind(f,_1,a))(b) == f(a,b)</pre></li>
+ <li><pre class="example">(bind(f,_2,_1))(a,b) == f(b,a)</pre></li>
+ </ul>
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.html b/docs/libraries/pl.html
new file mode 100644
index 0000000..d1d449d
--- /dev/null
+++ b/docs/libraries/pl.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><strong>pl</strong></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl</code></h1>
+<p>Entry point for loading all PL libraries only on demand, into the global space.</p>
+<p> Requiring &lsquo;pl&rsquo; means that whenever a module is implicitly accesssed
+ (e.g. <a href="../libraries/pl.utils.html#split">utils.split</a>)
+ then that module is dynamically loaded. The submodules are all brought into
+ the global space.
+Updated to use <a href="../libraries/pl.import_into.html#">pl.import_into</a></p>
+
+
+
+<br/>
+<br/>
+
+
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.import_into.html b/docs/libraries/pl.import_into.html
new file mode 100644
index 0000000..74ea5c6
--- /dev/null
+++ b/docs/libraries/pl.import_into.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><strong>pl.import_into</strong></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.import_into</code></h1>
+<p>PL loader, for loading all PL libraries, only on demand.</p>
+<p> Whenever a module is implicitly accesssed, the table will have the module automatically injected.
+ (e.g. <code>_ENV.tablex</code>)
+ then that module is dynamically loaded. The submodules are all brought into
+ the table that is provided as the argument, or returned in a new table.
+ If a table is provided, that table&rsquo;s metatable is clobbered, but the values are not.
+ This module returns a single function, which is passed the environment.
+ If this is <code>true</code>, then return a &lsquo;shadow table&rsquo; as the module
+ See <a href="../manual/01-introduction.md.html#To_Inject_or_not_to_Inject_">the Guide</a></p>
+
+
+
+<br/>
+<br/>
+
+
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.input.html b/docs/libraries/pl.input.html
new file mode 100644
index 0000000..cbdb255
--- /dev/null
+++ b/docs/libraries/pl.input.html
@@ -0,0 +1,333 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><strong>pl.input</strong></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.input</code></h1>
+<p>Iterators for extracting words or numbers from an input source.</p>
+<p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+<span class="keyword">local</span> total,n = seq.sum(input.numbers())
+<span class="global">print</span>(<span class="string">'average'</span>,total/n)
+</pre>
+
+
+<p> <em>source</em> is defined as a string or a file-like object (i.e. has a read() method which returns the next line)</p>
+
+<p> See <a href="../manual/06-data.md.html#Reading_Unstructured_Text_Data">here</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a></p></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#alltokens">alltokens (getter, pattern[, fn])</a></td>
+ <td class="summary">create an iterator over all tokens.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#create_getter">create_getter (f)</a></td>
+ <td class="summary">create a function which grabs the next value from a source.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#numbers">numbers (f)</a></td>
+ <td class="summary">generate a sequence of numbers from a source.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#words">words (f)</a></td>
+ <td class="summary">generate a sequence of words from a source.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#fields">fields (ids, delim, f, opts)</a></td>
+ <td class="summary">parse an input source into fields.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "alltokens"></a>
+ <strong>alltokens (getter, pattern[, fn])</strong>
+ </dt>
+ <dd>
+ create an iterator over all tokens.
+ based on allwords from PiL, 7.1
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">getter</span>
+ <span class="types"><span class="type">func</span></span>
+ any function that returns a line of text
+ </li>
+ <li><span class="parameter">pattern</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+
+ </li>
+ <li><span class="parameter">fn</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ Optionally can pass a function to process each token as it&rsquo;s found.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an iterator
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "create_getter"></a>
+ <strong>create_getter (f)</strong>
+ </dt>
+ <dd>
+ create a function which grabs the next value from a source. If the source is a string, then the getter
+ will return the string and thereafter return nil. If not specified then the source is assumed to be stdin.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a string or a file-like object (i.e. has a read() method which returns the next line)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a getter function
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "numbers"></a>
+ <strong>numbers (f)</strong>
+ </dt>
+ <dd>
+ generate a sequence of numbers from a source.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ A source
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ An iterator
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "words"></a>
+ <strong>words (f)</strong>
+ </dt>
+ <dd>
+ generate a sequence of words from a source.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ A source
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ An iterator
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "fields"></a>
+ <strong>fields (ids, delim, f, opts)</strong>
+ </dt>
+ <dd>
+ parse an input source into fields.
+ By default, will fail if it cannot convert a field to a number.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">ids</span>
+ a list of field indices, or a maximum field index
+ </li>
+ <li><span class="parameter">delim</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ delimiter to parse fields (default space)
+ </li>
+ <li><span class="parameter">f</span>
+ a source @see create_getter
+ </li>
+ <li><span class="parameter">opts</span>
+ <span class="types"><span class="type">tab</span></span>
+ option table, <code>{no_fail=true}</code>
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an iterator with the field values
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">for</span> x,y <span class="keyword">in</span> fields {<span class="number">2</span>,<span class="number">3</span>} <span class="keyword">do</span> <span class="global">print</span>(x,y) <span class="keyword">end</span> <span class="comment">-- 2nd and 3rd fields from stdin</span></pre>
+ </ul>
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.lapp.html b/docs/libraries/pl.lapp.html
new file mode 100644
index 0000000..4f15198
--- /dev/null
+++ b/docs/libraries/pl.lapp.html
@@ -0,0 +1,383 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+<li><a href="#Fields">Fields</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><strong>pl.lapp</strong></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.lapp</code></h1>
+<p>Simple command-line parsing using human-readable specification.</p>
+<p> Supports GNU-style parameters.</p>
+
+<pre>
+lapp = <span class="global">require</span> <span class="string">'pl.lapp'</span>
+<span class="keyword">local</span> args = lapp <span class="string">[[
+Does some calculations
+ -o,--offset (default 0.0) Offset to add to scaled number
+ -s,--scale (number) Scaling factor
+ &lt;number&gt; (number) Number to be scaled
+]]</span>
+
+<span class="global">print</span>(args.offset + args.scale * args.number)
+</pre>
+
+
+<p> Lines beginning with <code>&apos;-&apos;</code> are flags; there may be a short and a long name;
+ lines beginning with <code>&apos;&lt;var&gt;&apos;</code> are arguments. Anything in parens after
+ the flag/argument is either a default, a type name or a range constraint.</p>
+
+<p> See <a href="../manual/08-additional.md.html#Command_line_Programs_with_Lapp">the Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.sip.html#">pl.sip</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#quit">quit (msg, no_usage)</a></td>
+ <td class="summary">quit this script immediately.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#error">error (msg, no_usage)</a></td>
+ <td class="summary">print an error to stderr and quit.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#open">open (file[, opt])</a></td>
+ <td class="summary">open a file.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#assert">assert (condn, msg)</a></td>
+ <td class="summary">quit if the condition is false.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#add_type">add_type (name, converter[, constraint])</a></td>
+ <td class="summary">add a new type to Lapp.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#process_options_string">process_options_string (str, args)</a></td>
+ <td class="summary">process a Lapp options string.</td>
+ </tr>
+</table>
+<h2><a href="#Fields">Fields</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#show_usage_error">show_usage_error</a></td>
+ <td class="summary">controls whether to dump usage on error.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "quit"></a>
+ <strong>quit (msg, no_usage)</strong>
+ </dt>
+ <dd>
+ quit this script immediately.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">msg</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ optional message
+ </li>
+ <li><span class="parameter">no_usage</span>
+ <span class="types"><span class="type">bool</span></span>
+ suppress &lsquo;usage&rsquo; display
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "error"></a>
+ <strong>error (msg, no_usage)</strong>
+ </dt>
+ <dd>
+ print an error to stderr and quit.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">msg</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a message
+ </li>
+ <li><span class="parameter">no_usage</span>
+ <span class="types"><span class="type">bool</span></span>
+ suppress &lsquo;usage&rsquo; display
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "open"></a>
+ <strong>open (file[, opt])</strong>
+ </dt>
+ <dd>
+ open a file.
+ This will quit on error, and keep a list of file objects for later cleanup.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">file</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ filename
+ </li>
+ <li><span class="parameter">opt</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ same as second parameter of <a href="https://www.lua.org/manual/5.1/manual.html#pdf-io.open">io.open</a>
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "assert"></a>
+ <strong>assert (condn, msg)</strong>
+ </dt>
+ <dd>
+ quit if the condition is false.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">condn</span>
+ <span class="types"><span class="type">bool</span></span>
+ a condition
+ </li>
+ <li><span class="parameter">msg</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ message text
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "add_type"></a>
+ <strong>add_type (name, converter[, constraint])</strong>
+ </dt>
+ <dd>
+ add a new type to Lapp. These appear in parens after the value like
+ a range constraint, e.g. &lsquo;<ival> (integer) Process PID&rsquo;
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">name</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ name of type
+ </li>
+ <li><span class="parameter">converter</span>
+ either a function to convert values, or a Lua type name.
+ </li>
+ <li><span class="parameter">constraint</span>
+ <span class="types"><span class="type">func</span></span>
+ optional function to verify values, should use lapp.error
+ if failed.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "process_options_string"></a>
+ <strong>process_options_string (str, args)</strong>
+ </dt>
+ <dd>
+ process a Lapp options string.
+ Usually called as <code>lapp()</code>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">str</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the options text
+ </li>
+ <li><span class="parameter">args</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">{string}</a></span>
+ a table of arguments (default is <code>_G.arg</code>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table with parameter-value pairs
+ </ol>
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Fields"></a>Fields</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "show_usage_error"></a>
+ <strong>show_usage_error</strong>
+ </dt>
+ <dd>
+ controls whether to dump usage on error.
+ Defaults to true
+
+
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.lexer.html b/docs/libraries/pl.lexer.html
new file mode 100644
index 0000000..0760855
--- /dev/null
+++ b/docs/libraries/pl.lexer.html
@@ -0,0 +1,525 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><strong>pl.lexer</strong></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.lexer</code></h1>
+<p>Lexical scanner for creating a sequence of tokens from text.</p>
+<p> <code>lexer.scan(s)</code> returns an iterator over all tokens found in the
+ string <code>s</code>. This iterator returns two values, a token type string
+ (such as &lsquo;string&rsquo; for quoted string, &lsquo;iden&rsquo; for identifier) and the value of the
+ token.</p>
+
+<p> Versions specialized for Lua and C are available; these also handle block comments
+ and classify keywords as &lsquo;keyword&rsquo; tokens. For example:</p>
+
+<pre>
+&gt; s = <span class="string">'for i=1,n do'</span>
+&gt; <span class="keyword">for</span> t,v <span class="keyword">in</span> lexer.lua(s) <span class="keyword">do</span> <span class="global">print</span>(t,v) <span class="keyword">end</span>
+keyword <span class="keyword">for</span>
+iden i
+= =
+number <span class="number">1</span>
+, ,
+iden n
+keyword <span class="keyword">do</span>
+</pre>
+
+
+<p> See the Guide for further <a href="../manual/06-data.md.html#Lexical_Scanning">discussion</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#scan">scan (s, matches[, filter[, options]])</a></td>
+ <td class="summary">create a plain token iterator from a string or file-like object.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#insert">insert (tok, a1, a2)</a></td>
+ <td class="summary">insert tokens into a stream.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getline">getline (tok)</a></td>
+ <td class="summary">get everything in a stream upto a newline.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#lineno">lineno (tok)</a></td>
+ <td class="summary">get current line number.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getrest">getrest (tok)</a></td>
+ <td class="summary">get the rest of the stream.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#get_keywords">get_keywords ()</a></td>
+ <td class="summary">get the Lua keywords as a set-like table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#lua">lua (s[, filter[, options]])</a></td>
+ <td class="summary">create a Lua token iterator from a string or file-like object.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#cpp">cpp (s[, filter[, options]])</a></td>
+ <td class="summary">create a C/C++ token iterator from a string or file-like object.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#get_separated_list">get_separated_list (tok[, endtoken=')'[, delim=']])</a></td>
+ <td class="summary">get a list of parameters separated by a delimiter from a stream.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#skipws">skipws (tok)</a></td>
+ <td class="summary">get the next non-space token from the stream.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#expecting">expecting (tok, expected_type, no_skip_ws)</a></td>
+ <td class="summary">get the next token, which must be of the expected type.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "scan"></a>
+ <strong>scan (s, matches[, filter[, options]])</strong>
+ </dt>
+ <dd>
+ create a plain token iterator from a string or file-like object.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">file</span></span>
+ a string or a file-like object with <code>:read()</code> method returning lines.
+ </li>
+ <li><span class="parameter">matches</span>
+ <span class="types"><span class="type">tab</span></span>
+ an optional match table - array of token descriptions.
+ A token is described by a <code>{pattern, action}</code> pair, where <code>pattern</code> should match
+ token body and <code>action</code> is a function called when a token of described type is found.
+ </li>
+ <li><span class="parameter">filter</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table of token types to exclude, by default <code>{space=true}</code>
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">options</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table of options; by default, <code>{number=true,string=true}</code>,
+ which means convert numbers and strip string quotes.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "insert"></a>
+ <strong>insert (tok, a1, a2)</strong>
+ </dt>
+ <dd>
+ insert tokens into a stream.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tok</span>
+ a token stream
+ </li>
+ <li><span class="parameter">a1</span>
+ a string is the type, a table is a token list and
+ a function is assumed to be a token-like iterator (returns type &amp; value)
+ </li>
+ <li><span class="parameter">a2</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string is the value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "getline"></a>
+ <strong>getline (tok)</strong>
+ </dt>
+ <dd>
+ get everything in a stream upto a newline.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tok</span>
+ a token stream
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "lineno"></a>
+ <strong>lineno (tok)</strong>
+ </dt>
+ <dd>
+ get current line number.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tok</span>
+ a token stream
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the line number.
+ if the input source is a file-like object,
+ also return the column.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "getrest"></a>
+ <strong>getrest (tok)</strong>
+ </dt>
+ <dd>
+ get the rest of the stream.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tok</span>
+ a token stream
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "get_keywords"></a>
+ <strong>get_keywords ()</strong>
+ </dt>
+ <dd>
+ get the Lua keywords as a set-like table.
+ So <code>res[&quot;and&quot;]</code> etc would be <code>true</code>.
+
+
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "lua"></a>
+ <strong>lua (s[, filter[, options]])</strong>
+ </dt>
+ <dd>
+ create a Lua token iterator from a string or file-like object.
+ Will return the token type and value.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">filter</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table of token types to exclude, by default <code>{space=true,comments=true}</code>
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">options</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table of options; by default, <code>{number=true,string=true}</code>,
+ which means convert numbers and strip string quotes.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "cpp"></a>
+ <strong>cpp (s[, filter[, options]])</strong>
+ </dt>
+ <dd>
+ create a C/C++ token iterator from a string or file-like object.
+ Will return the token type type and value.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">filter</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table of token types to exclude, by default <code>{space=true,comments=true}</code>
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">options</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table of options; by default, <code>{number=true,string=true}</code>,
+ which means convert numbers and strip string quotes.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "get_separated_list"></a>
+ <strong>get_separated_list (tok[, endtoken=')'[, delim=']])</strong>
+ </dt>
+ <dd>
+ get a list of parameters separated by a delimiter from a stream.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tok</span>
+ the token stream
+ </li>
+ <li><span class="parameter">endtoken</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ end of list. Can be &lsquo;\n&rsquo;
+ (<em>default</em> ')')
+ </li>
+ <li><span class="parameter">delim</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ separator
+ (<em>default</em> ')
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list of token lists.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "skipws"></a>
+ <strong>skipws (tok)</strong>
+ </dt>
+ <dd>
+ get the next non-space token from the stream.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tok</span>
+ the token stream.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "expecting"></a>
+ <strong>expecting (tok, expected_type, no_skip_ws)</strong>
+ </dt>
+ <dd>
+ get the next token, which must be of the expected type.
+ Throws an error if this type does not match!
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tok</span>
+ the token stream
+ </li>
+ <li><span class="parameter">expected_type</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the token type
+ </li>
+ <li><span class="parameter">no_skip_ws</span>
+ <span class="types"><span class="type">bool</span></span>
+ whether we should skip whitespace
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.luabalanced.html b/docs/libraries/pl.luabalanced.html
new file mode 100644
index 0000000..53dd851
--- /dev/null
+++ b/docs/libraries/pl.luabalanced.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><strong>pl.luabalanced</strong></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.luabalanced</code></h1>
+<p>Extract delimited Lua sequences from strings.</p>
+<p> Inspired by Damian Conway&rsquo;s Text::Balanced in Perl. <br/>
+ <ul>
+ <li>[1] <a href="http://lua-users.org/wiki/LuaBalanced">Lua Wiki Page</a></li>
+ <li>[2] http://search.cpan.org/dist/Text-Balanced/lib/Text/Balanced.pm</li>
+ </ul> <br/>
+ <pre class=example>
+ local lb = require &ldquo;pl.luabalanced&rdquo;
+ &ndash;Extract Lua expression starting at position 4.
+ print(lb.match_expression(&ldquo;if x<sup>2</sup> + x > 5 then print(x) end&rdquo;, 4))
+ &ndash;> x<sup>2</sup> + x > 5 16
+ &ndash;Extract Lua string starting at (default) position 1.
+ print(lb.match_string([[&ldquo;test\"123&rdquo; .. &ldquo;more&rdquo;]]))
+ &ndash;> &ldquo;test\"123&rdquo; 12
+ </pre>
+ &copy; 2008, David Manura, Licensed under the same terms as Lua (MIT license).</p>
+
+
+
+<br/>
+<br/>
+
+
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.operator.html b/docs/libraries/pl.operator.html
new file mode 100644
index 0000000..b47f344
--- /dev/null
+++ b/docs/libraries/pl.operator.html
@@ -0,0 +1,812 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+<li><a href="#Tables">Tables</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><strong>pl.operator</strong></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.operator</code></h1>
+<p>Lua operators available as functions.</p>
+<p> (similar to the Python module of the same name)</p>
+
+<p> There is a module field <a href="../libraries/pl.operator.html#optable">optable</a> which maps the operator strings
+ onto these functions, e.g. <code>operator.optable[&apos;()&apos;]==operator.call</code></p>
+
+<p> Operator strings like &lsquo;>&rsquo; and &lsquo;{}&rsquo; can be passed to most Penlight functions
+ expecting a function argument.</p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#call">call (fn, ...)</a></td>
+ <td class="summary">apply function to some arguments <strong>()</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#index">index (t, k)</a></td>
+ <td class="summary">get the indexed value from a table <strong>[]</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#eq">eq (a, b)</a></td>
+ <td class="summary">returns true if arguments are equal <strong>==</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#neq">neq (a, b)</a></td>
+ <td class="summary">returns true if arguments are not equal <strong>~=</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#lt">lt (a, b)</a></td>
+ <td class="summary">returns true if a is less than b <strong>&lt;</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#le">le (a, b)</a></td>
+ <td class="summary">returns true if a is less or equal to b <strong>&lt;=</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#gt">gt (a, b)</a></td>
+ <td class="summary">returns true if a is greater than b <strong>></strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#ge">ge (a, b)</a></td>
+ <td class="summary">returns true if a is greater or equal to b <strong>>=</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#len">len (a)</a></td>
+ <td class="summary">returns length of string or table <strong>#</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#add">add (a, b)</a></td>
+ <td class="summary">add two values <strong>+</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#sub">sub (a, b)</a></td>
+ <td class="summary">subtract b from a <strong>-</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#mul">mul (a, b)</a></td>
+ <td class="summary">multiply two values <strong>*</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#div">div (a, b)</a></td>
+ <td class="summary">divide first value by second <strong>/</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pow">pow (a, b)</a></td>
+ <td class="summary">raise first to the power of second <strong>^</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#mod">mod (a, b)</a></td>
+ <td class="summary">modulo; remainder of a divided by b <strong>%</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#concat">concat (a, b)</a></td>
+ <td class="summary">concatenate two values (either strings or <code>__concat</code> defined) <strong>..</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#unm">unm (a)</a></td>
+ <td class="summary">return the negative of a value <strong>-</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#lnot">lnot (a)</a></td>
+ <td class="summary">false if value evaluates as true <strong>not</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#land">land (a, b)</a></td>
+ <td class="summary">true if both values evaluate as true <strong>and</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#lor">lor (a, b)</a></td>
+ <td class="summary">true if either value evaluate as true <strong>or</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#table">table (...)</a></td>
+ <td class="summary">make a table from the arguments <strong>{}</strong></td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#match">match (a, b)</a></td>
+ <td class="summary">match two strings <strong>~</strong>.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#nop">nop (...)</a></td>
+ <td class="summary">the null operation.</td>
+ </tr>
+</table>
+<h2><a href="#Tables">Tables</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#optable">optable</a></td>
+ <td class="summary">Map from operator symbol to function.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "call"></a>
+ <strong>call (fn, ...)</strong>
+ </dt>
+ <dd>
+ apply function to some arguments <strong>()</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fn</span>
+ a function or callable object
+ </li>
+ <li><span class="parameter">...</span>
+ arguments
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "index"></a>
+ <strong>index (t, k)</strong>
+ </dt>
+ <dd>
+ get the indexed value from a table <strong>[]</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table or any indexable object
+ </li>
+ <li><span class="parameter">k</span>
+ the key
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "eq"></a>
+ <strong>eq (a, b)</strong>
+ </dt>
+ <dd>
+ returns true if arguments are equal <strong>==</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "neq"></a>
+ <strong>neq (a, b)</strong>
+ </dt>
+ <dd>
+ returns true if arguments are not equal <strong>~=</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "lt"></a>
+ <strong>lt (a, b)</strong>
+ </dt>
+ <dd>
+ returns true if a is less than b <strong>&lt;</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "le"></a>
+ <strong>le (a, b)</strong>
+ </dt>
+ <dd>
+ returns true if a is less or equal to b <strong>&lt;=</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "gt"></a>
+ <strong>gt (a, b)</strong>
+ </dt>
+ <dd>
+ returns true if a is greater than b <strong>></strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "ge"></a>
+ <strong>ge (a, b)</strong>
+ </dt>
+ <dd>
+ returns true if a is greater or equal to b <strong>>=</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "len"></a>
+ <strong>len (a)</strong>
+ </dt>
+ <dd>
+ returns length of string or table <strong>#</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ a string or a table
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "add"></a>
+ <strong>add (a, b)</strong>
+ </dt>
+ <dd>
+ add two values <strong>+</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "sub"></a>
+ <strong>sub (a, b)</strong>
+ </dt>
+ <dd>
+ subtract b from a <strong>-</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "mul"></a>
+ <strong>mul (a, b)</strong>
+ </dt>
+ <dd>
+ multiply two values <strong>*</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "div"></a>
+ <strong>div (a, b)</strong>
+ </dt>
+ <dd>
+ divide first value by second <strong>/</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pow"></a>
+ <strong>pow (a, b)</strong>
+ </dt>
+ <dd>
+ raise first to the power of second <strong>^</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "mod"></a>
+ <strong>mod (a, b)</strong>
+ </dt>
+ <dd>
+ modulo; remainder of a divided by b <strong>%</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "concat"></a>
+ <strong>concat (a, b)</strong>
+ </dt>
+ <dd>
+ concatenate two values (either strings or <code>__concat</code> defined) <strong>..</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "unm"></a>
+ <strong>unm (a)</strong>
+ </dt>
+ <dd>
+ return the negative of a value <strong>-</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "lnot"></a>
+ <strong>lnot (a)</strong>
+ </dt>
+ <dd>
+ false if value evaluates as true <strong>not</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "land"></a>
+ <strong>land (a, b)</strong>
+ </dt>
+ <dd>
+ true if both values evaluate as true <strong>and</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "lor"></a>
+ <strong>lor (a, b)</strong>
+ </dt>
+ <dd>
+ true if either value evaluate as true <strong>or</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ value
+ </li>
+ <li><span class="parameter">b</span>
+ value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "table"></a>
+ <strong>table (...)</strong>
+ </dt>
+ <dd>
+ make a table from the arguments <strong>{}</strong>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">...</span>
+ non-nil arguments
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "match"></a>
+ <strong>match (a, b)</strong>
+ </dt>
+ <dd>
+ match two strings <strong>~</strong>.
+ uses <a href="https://www.lua.org/manual/5.1/manual.html#pdf-string.find">string.find</a>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+
+ </li>
+ <li><span class="parameter">b</span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "nop"></a>
+ <strong>nop (...)</strong>
+ </dt>
+ <dd>
+ the null operation.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">...</span>
+ arguments
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the arguments
+ </ol>
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Tables"></a>Tables</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "optable"></a>
+ <strong>optable</strong>
+ </dt>
+ <dd>
+ <p>Map from operator symbol to function.
+ Most of these map directly from operators;
+ But note these extras</p>
+
+<ul>
+<li><strong>&lsquo;()&rsquo;</strong> <a href="../libraries/pl.operator.html#call">call</a></li>
+<li><strong>&lsquo;[]&rsquo;</strong> <a href="../libraries/pl.operator.html#index">index</a></li>
+<li><strong>&lsquo;{}&rsquo;</strong> <a href="../libraries/pl.operator.html#table">table</a></li>
+<li><strong>&lsquo;~&rsquo;</strong> <a href="../libraries/pl.operator.html#match">match</a></li>
+</ul>
+
+
+
+ <h3>Fields:</h3>
+ <ul>
+ <li><span class="parameter">operator</span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.path.html b/docs/libraries/pl.path.html
new file mode 100644
index 0000000..ab52a07
--- /dev/null
+++ b/docs/libraries/pl.path.html
@@ -0,0 +1,900 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+<li><a href="#Fields">Fields</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><strong>pl.path</strong></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.path</code></h1>
+<p>Path manipulation and file queries.</p>
+<p> This is modelled after Python&rsquo;s os.path library (10.1); see <a href="../manual/04-paths.md.html#">the Guide</a>.</p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="http://stevedonovan.github.io/lua-stdlibs/modules/lfs.html">lfs</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#isdir">isdir (P)</a></td>
+ <td class="summary">is this a directory?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isfile">isfile (P)</a></td>
+ <td class="summary">is this a file?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getsize">getsize (P)</a></td>
+ <td class="summary">return size of a file.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#exists">exists (P)</a></td>
+ <td class="summary">does a path exist?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getatime">getatime (P)</a></td>
+ <td class="summary">Return the time of last access as the number of seconds since the epoch.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getmtime">getmtime (P)</a></td>
+ <td class="summary">Return the time of last modification</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getctime">getctime (P)</a></td>
+ <td class="summary">Return the system&rsquo;s ctime.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#splitpath">splitpath (P)</a></td>
+ <td class="summary">given a path, return the directory part and a file part.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#abspath">abspath (P[, pwd])</a></td>
+ <td class="summary">return an absolute path.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#splitext">splitext (P)</a></td>
+ <td class="summary">given a path, return the root part and the extension part.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#dirname">dirname (P)</a></td>
+ <td class="summary">return the directory part of a path</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#basename">basename (P)</a></td>
+ <td class="summary">return the file part of a path</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#extension">extension (P)</a></td>
+ <td class="summary">get the extension part of a path.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isabs">isabs (P)</a></td>
+ <td class="summary">is this an absolute path?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#join">join (p1, p2, ...)</a></td>
+ <td class="summary">return the path resulting from combining the individual paths.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#normcase">normcase (P)</a></td>
+ <td class="summary">normalize the case of a pathname.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#normpath">normpath (P)</a></td>
+ <td class="summary">normalize a path name.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#relpath">relpath (P[, start])</a></td>
+ <td class="summary">relative path from current directory or optional start point</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#expanduser">expanduser (P)</a></td>
+ <td class="summary">Replace a starting &lsquo;~&rsquo; with the user&rsquo;s home directory.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#tmpname">tmpname ()</a></td>
+ <td class="summary">Return a suitable full path to a new temporary file name.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#common_prefix">common_prefix (path1, path2)</a></td>
+ <td class="summary">return the largest common prefix path of two paths.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#package_path">package_path (mod)</a></td>
+ <td class="summary">return the full path where a particular Lua module would be found.</td>
+ </tr>
+</table>
+<h2><a href="#Fields">Fields</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#dir">dir</a></td>
+ <td class="summary">Lua iterator over the entries of a given directory.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#mkdir">mkdir</a></td>
+ <td class="summary">Creates a directory.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#rmdir">rmdir</a></td>
+ <td class="summary">Removes a directory.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#currentdir">currentdir</a></td>
+ <td class="summary">Get the working directory.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#chdir">chdir</a></td>
+ <td class="summary">Changes the working directory.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_windows">is_windows</a></td>
+ <td class="summary">are we running Windows?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#sep">sep</a></td>
+ <td class="summary">path separator for this platform.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#dirsep">dirsep</a></td>
+ <td class="summary">separator for PATH for this platform</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "isdir"></a>
+ <strong>isdir (P)</strong>
+ </dt>
+ <dd>
+ is this a directory?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isfile"></a>
+ <strong>isfile (P)</strong>
+ </dt>
+ <dd>
+ is this a file?.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "getsize"></a>
+ <strong>getsize (P)</strong>
+ </dt>
+ <dd>
+ return size of a file.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "exists"></a>
+ <strong>exists (P)</strong>
+ </dt>
+ <dd>
+ does a path exist?.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the file path if it exists, nil otherwise
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "getatime"></a>
+ <strong>getatime (P)</strong>
+ </dt>
+ <dd>
+ Return the time of last access as the number of seconds since the epoch.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "getmtime"></a>
+ <strong>getmtime (P)</strong>
+ </dt>
+ <dd>
+ Return the time of last modification
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "getctime"></a>
+ <strong>getctime (P)</strong>
+ </dt>
+ <dd>
+ Return the system&rsquo;s ctime.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "splitpath"></a>
+ <strong>splitpath (P)</strong>
+ </dt>
+ <dd>
+ given a path, return the directory part and a file part.
+ if there&rsquo;s no directory part, the first value will be empty
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "abspath"></a>
+ <strong>abspath (P[, pwd])</strong>
+ </dt>
+ <dd>
+ return an absolute path.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ <li><span class="parameter">pwd</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ optional start path to use (default is current dir)
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "splitext"></a>
+ <strong>splitext (P)</strong>
+ </dt>
+ <dd>
+ given a path, return the root part and the extension part.
+ if there&rsquo;s no extension part, the second value will be empty
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ root part</li>
+ <li>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ extension part (maybe empty)</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "dirname"></a>
+ <strong>dirname (P)</strong>
+ </dt>
+ <dd>
+ return the directory part of a path
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "basename"></a>
+ <strong>basename (P)</strong>
+ </dt>
+ <dd>
+ return the file part of a path
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "extension"></a>
+ <strong>extension (P)</strong>
+ </dt>
+ <dd>
+ get the extension part of a path.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isabs"></a>
+ <strong>isabs (P)</strong>
+ </dt>
+ <dd>
+ is this an absolute path?.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "join"></a>
+ <strong>join (p1, p2, ...)</strong>
+ </dt>
+ <dd>
+ return the path resulting from combining the individual paths.
+ if the second (or later) path is absolute, we return the last absolute path (joined with any non-absolute paths following).
+ empty elements (except the last) will be ignored.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">p1</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ <li><span class="parameter">p2</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ <li><span class="parameter">...</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ more file paths
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "normcase"></a>
+ <strong>normcase (P)</strong>
+ </dt>
+ <dd>
+ normalize the case of a pathname. On Unix, this returns the path unchanged;
+ for Windows, it converts the path to lowercase, and it also converts forward slashes
+ to backward slashes.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "normpath"></a>
+ <strong>normpath (P)</strong>
+ </dt>
+ <dd>
+ normalize a path name.
+ A//B, A/./B and A/foo/../B all become A/B.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "relpath"></a>
+ <strong>relpath (P[, start])</strong>
+ </dt>
+ <dd>
+ relative path from current directory or optional start point
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a path
+ </li>
+ <li><span class="parameter">start</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ optional start point (default current directory)
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "expanduser"></a>
+ <strong>expanduser (P)</strong>
+ </dt>
+ <dd>
+ Replace a starting &lsquo;~&rsquo; with the user&rsquo;s home directory.
+ In windows, if HOME isn&rsquo;t set, then USERPROFILE is used in preference to
+ HOMEDRIVE HOMEPATH. This is guaranteed to be writeable on all versions of Windows.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">P</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ A file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "tmpname"></a>
+ <strong>tmpname ()</strong>
+ </dt>
+ <dd>
+ Return a suitable full path to a new temporary file name.
+ unlike os.tmpnam(), it always gives you a writeable path (uses TEMP environment variable on Windows)
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "common_prefix"></a>
+ <strong>common_prefix (path1, path2)</strong>
+ </dt>
+ <dd>
+ return the largest common prefix path of two paths.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">path1</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a file path
+ </li>
+ <li><span class="parameter">path2</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a file path
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "package_path"></a>
+ <strong>package_path (mod)</strong>
+ </dt>
+ <dd>
+ return the full path where a particular Lua module would be found.
+ Both package.path and package.cpath is searched, so the result may
+ either be a Lua file or a shared library.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">mod</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ name of the module
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ on success: path of module, lua or binary</li>
+ <li>
+ on error: nil,error string</li>
+ </ol>
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Fields"></a>Fields</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "dir"></a>
+ <strong>dir</strong>
+ </dt>
+ <dd>
+ Lua iterator over the entries of a given directory.
+ Behaves like <a href="http://stevedonovan.github.io/lua-stdlibs/modules/lfs.html#dir">lfs.dir</a>
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "mkdir"></a>
+ <strong>mkdir</strong>
+ </dt>
+ <dd>
+ Creates a directory.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "rmdir"></a>
+ <strong>rmdir</strong>
+ </dt>
+ <dd>
+ Removes a directory.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "currentdir"></a>
+ <strong>currentdir</strong>
+ </dt>
+ <dd>
+ Get the working directory.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "chdir"></a>
+ <strong>chdir</strong>
+ </dt>
+ <dd>
+ Changes the working directory.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "is_windows"></a>
+ <strong>is_windows</strong>
+ </dt>
+ <dd>
+ are we running Windows?
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "sep"></a>
+ <strong>sep</strong>
+ </dt>
+ <dd>
+ path separator for this platform.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "dirsep"></a>
+ <strong>dirsep</strong>
+ </dt>
+ <dd>
+ separator for PATH for this platform
+
+
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.permute.html b/docs/libraries/pl.permute.html
new file mode 100644
index 0000000..b239a8b
--- /dev/null
+++ b/docs/libraries/pl.permute.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><strong>pl.permute</strong></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.permute</code></h1>
+<p>Permutation operations.</p>
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.tablex.html#">pl.tablex</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#iter">iter (a)</a></td>
+ <td class="summary">an iterator over all permutations of the elements of a list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#table">table (a)</a></td>
+ <td class="summary">construct a table containing all the permutations of a list.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "iter"></a>
+ <strong>iter (a)</strong>
+ </dt>
+ <dd>
+ an iterator over all permutations of the elements of a list.
+ Please note that the same list is returned each time, so do not keep references!
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ list-like table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an iterator which provides the next permutation as a list
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "table"></a>
+ <strong>table (a)</strong>
+ </dt>
+ <dd>
+ construct a table containing all the permutations of a list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ list-like table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table of tables
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">permute.<span class="global">table</span> {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="comment">--&gt; {{2,3,1},{3,2,1},{3,1,2},{1,3,2},{2,1,3},{1,2,3}}</span></pre>
+ </ul>
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.pretty.html b/docs/libraries/pl.pretty.html
new file mode 100644
index 0000000..78a25a6
--- /dev/null
+++ b/docs/libraries/pl.pretty.html
@@ -0,0 +1,345 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><strong>pl.pretty</strong></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.pretty</code></h1>
+<p>Pretty-printing Lua tables.</p>
+<p> Also provides a sandboxed Lua table reader and
+ a function to present large numbers in human-friendly format.</p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.lexer.html#">pl.lexer</a>, <a href="../libraries/pl.stringx.html#">pl.stringx</a>, <a href="https://www.lua.org/manual/5.1/manual.html#5.9">debug</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#read">read (s)</a></td>
+ <td class="summary">Read a string representation of a Lua table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#load">load (s[, env[, paranoid]])</a></td>
+ <td class="summary">Read a Lua chunk.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#write">write (tbl[, space[, not_clever]])</a></td>
+ <td class="summary">Create a string representation of a Lua table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#dump">dump (t[, filename])</a></td>
+ <td class="summary">Dump a Lua table out to a file or stdout.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#number">number (num[, kind[, prec]])</a></td>
+ <td class="summary">Format large numbers nicely for human consumption.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "read"></a>
+ <strong>read (s)</strong>
+ </dt>
+ <dd>
+ Read a string representation of a Lua table.
+ This function loads and runs the string as Lua code, but bails out
+ if it contains a function definition.
+ Loaded string is executed in an empty environment.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ string to read in <code>{&hellip;}</code> format, possibly with some whitespace
+ before or after the curly braces. A single line comment may be present
+ at the beginning.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table in case of success.
+ If loading the string failed, return <code>nil</code> and error message.
+ If executing loaded string failed, return <code>nil</code> and the error it raised.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "load"></a>
+ <strong>load (s[, env[, paranoid]])</strong>
+ </dt>
+ <dd>
+ Read a Lua chunk.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ Lua code.
+ </li>
+ <li><span class="parameter">env</span>
+ <span class="types"><span class="type">tab</span></span>
+ environment used to run the code, empty by default.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">paranoid</span>
+ <span class="types"><span class="type">bool</span></span>
+ abort loading if any looping constructs a found in the code
+ and disable string methods.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the environment in case of success or <code>nil</code> and syntax or runtime error
+ if something went wrong.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "write"></a>
+ <strong>write (tbl[, space[, not_clever]])</strong>
+ </dt>
+ <dd>
+ Create a string representation of a Lua table.
+ This function never fails, but may complain by returning an
+ extra value. Normally puts out one item per line, using
+ the provided indent; set the second parameter to an empty string
+ if you want output on one line.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tbl</span>
+ <span class="types"><span class="type">tab</span></span>
+ Table to serialize to a string.
+ </li>
+ <li><span class="parameter">space</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ The indent to use.
+ Defaults to two spaces; pass an empty string for no indentation.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">not_clever</span>
+ <span class="types"><span class="type">bool</span></span>
+ Pass <code>true</code> for plain output, e.g <code>{[&apos;key&apos;]=1}</code>.
+ Defaults to <code>false</code>.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ a string</li>
+ <li>
+ an optional error message</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "dump"></a>
+ <strong>dump (t[, filename])</strong>
+ </dt>
+ <dd>
+ Dump a Lua table out to a file or stdout.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ The table to write to a file or stdout.
+ </li>
+ <li><span class="parameter">filename</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ File name to write too. Defaults to writing
+ to stdout.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "number"></a>
+ <strong>number (num[, kind[, prec]])</strong>
+ </dt>
+ <dd>
+ Format large numbers nicely for human consumption.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">num</span>
+ <span class="types"><a class="type" href="../libraries/pl.pretty.html#number">number</a></span>
+ a number.
+ </li>
+ <li><span class="parameter">kind</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ one of <code>&apos;M&apos;</code> (memory in <code>KiB</code>, <code>MiB</code>, etc.),
+ <code>&apos;N&apos;</code> (postfixes are <code>&apos;K&apos;</code>, <code>&apos;M&apos;</code> and <code>&apos;B&apos;</code>),
+ or <code>&apos;T&apos;</code> (use commas as thousands separator), <code>&apos;N&apos;</code> by default.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">prec</span>
+ <span class="types"><span class="type">int</span></span>
+ number of digits to use for <code>&apos;M&apos;</code> and <code>&apos;N&apos;</code>, <code>1</code> by default.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.seq.html b/docs/libraries/pl.seq.html
new file mode 100644
index 0000000..ee99af4
--- /dev/null
+++ b/docs/libraries/pl.seq.html
@@ -0,0 +1,889 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><strong>pl.seq</strong></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.seq</code></h1>
+<p>Manipulating iterators as sequences.</p>
+<p> See <a href="../manual/07-functional.md.html#Sequences">The Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.types.html#">pl.types</a>, <a href="https://www.lua.org/manual/5.1/manual.html#5.9">debug</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#matching">matching (s)</a></td>
+ <td class="summary">given a string, return a function(y) which matches y against the string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#list">list (t)</a></td>
+ <td class="summary">sequence adaptor for a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#keys">keys (t)</a></td>
+ <td class="summary">return the keys of the table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#range">range (start, finish)</a></td>
+ <td class="summary">create an iterator over a numerical range.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#minmax">minmax (iter)</a></td>
+ <td class="summary">return the minimum and the maximum value of the sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#sum">sum (iter, fn)</a></td>
+ <td class="summary">return the sum and element count of the sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#copy">copy (iter)</a></td>
+ <td class="summary">create a table from the sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#copy2">copy2 (iter, i1, i2)</a></td>
+ <td class="summary">create a table of pairs from the double-valued sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#copy_tuples">copy_tuples (iter)</a></td>
+ <td class="summary">create a table of &lsquo;tuples&rsquo; from a multi-valued sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#random">random (n, l, u)</a></td>
+ <td class="summary">return an iterator of random numbers.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#sort">sort (iter, comp)</a></td>
+ <td class="summary">return an iterator to the sorted elements of a sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#zip">zip (iter1, iter2)</a></td>
+ <td class="summary">return an iterator which returns elements of two sequences.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#count_map">count_map (iter)</a></td>
+ <td class="summary">Makes a table where the key/values are the values and value counts of the sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#printall">printall (iter, sep, nfields, fmt)</a></td>
+ <td class="summary">print out a sequence iter with a separator.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#map">map (fn, iter, arg)</a></td>
+ <td class="summary">return a sequence where every element of a sequence has been transformed
+ by a function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#filter">filter (iter, pred, arg)</a></td>
+ <td class="summary">filter a sequence using a predicate function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#reduce">reduce (fn, iter, initval)</a></td>
+ <td class="summary">&lsquo;reduce&rsquo; a sequence using a binary function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#take">take (iter, n)</a></td>
+ <td class="summary">take the first n values from the sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#skip">skip (iter, n)</a></td>
+ <td class="summary">skip the first n values of a sequence</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#enum">enum (iter)</a></td>
+ <td class="summary">a sequence with a sequence count and the original value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#mapmethod">mapmethod (iter, name, arg1, arg2)</a></td>
+ <td class="summary">map using a named method over a sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#last">last (iter)</a></td>
+ <td class="summary">a sequence of (last,current) values from another sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#foreach">foreach (iter, fn)</a></td>
+ <td class="summary">call the function on each element of the sequence.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#lines">lines (f, ...)</a></td>
+ <td class="summary">create a wrapped iterator over all lines in the file.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "matching"></a>
+ <strong>matching (s)</strong>
+ </dt>
+ <dd>
+ given a string, return a function(y) which matches y against the string.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ a string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "list"></a>
+ <strong>list (t)</strong>
+ </dt>
+ <dd>
+ sequence adaptor for a table. Note that if any generic function is
+ passed a table, it will automatically use seq.list()
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a list-like table
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">sum(list(t)) is the sum of all elements of t</pre></li>
+ <li><pre class="example"><span class="keyword">for</span> x <span class="keyword">in</span> list(t) <span class="keyword">do</span>...<span class="keyword">end</span></pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "keys"></a>
+ <strong>keys (t)</strong>
+ </dt>
+ <dd>
+ return the keys of the table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ an arbitrary table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ iterator over keys
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "range"></a>
+ <strong>range (start, finish)</strong>
+ </dt>
+ <dd>
+ create an iterator over a numerical range. Like the standard Python function xrange.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">start</span>
+ a number
+ </li>
+ <li><span class="parameter">finish</span>
+ a number greater than start
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "minmax"></a>
+ <strong>minmax (iter)</strong>
+ </dt>
+ <dd>
+ return the minimum and the maximum value of the sequence.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ minimum value</li>
+ <li>
+ maximum value</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "sum"></a>
+ <strong>sum (iter, fn)</strong>
+ </dt>
+ <dd>
+ return the sum and element count of the sequence.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ <li><span class="parameter">fn</span>
+ an optional function to apply to the values
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "copy"></a>
+ <strong>copy (iter)</strong>
+ </dt>
+ <dd>
+ create a table from the sequence. (This will make the result a List.)
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a List
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">copy(list(ls)) is equal to ls</pre></li>
+ <li><pre class="example">copy(list {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) == List{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}</pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "copy2"></a>
+ <strong>copy2 (iter, i1, i2)</strong>
+ </dt>
+ <dd>
+ create a table of pairs from the double-valued sequence.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a double-valued sequence
+ </li>
+ <li><span class="parameter">i1</span>
+ used to capture extra iterator values
+ </li>
+ <li><span class="parameter">i2</span>
+ as with pairs &amp; ipairs
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list-like table
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">copy2(<span class="global">ipairs</span>{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}) == {{<span class="number">1</span>,<span class="number">10</span>},{<span class="number">2</span>,<span class="number">20</span>},{<span class="number">3</span>,<span class="number">30</span>}}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "copy_tuples"></a>
+ <strong>copy_tuples (iter)</strong>
+ </dt>
+ <dd>
+ create a table of &lsquo;tuples&rsquo; from a multi-valued sequence.
+ A generalization of copy2 above
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a multiple-valued sequence
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list-like table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "random"></a>
+ <strong>random (n, l, u)</strong>
+ </dt>
+ <dd>
+ return an iterator of random numbers.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">n</span>
+ the length of the sequence
+ </li>
+ <li><span class="parameter">l</span>
+ same as the first optional argument to math.random
+ </li>
+ <li><span class="parameter">u</span>
+ same as the second optional argument to math.random
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a sequence
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "sort"></a>
+ <strong>sort (iter, comp)</strong>
+ </dt>
+ <dd>
+ return an iterator to the sorted elements of a sequence.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ <li><span class="parameter">comp</span>
+ an optional comparison function (comp(x,y) is true if x &lt; y)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "zip"></a>
+ <strong>zip (iter1, iter2)</strong>
+ </dt>
+ <dd>
+ return an iterator which returns elements of two sequences.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter1</span>
+ a sequence
+ </li>
+ <li><span class="parameter">iter2</span>
+ a sequence
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">for</span> x,y <span class="keyword">in</span> seq.zip(ls1,ls2) <span class="keyword">do</span>....<span class="keyword">end</span></pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "count_map"></a>
+ <strong>count_map (iter)</strong>
+ </dt>
+ <dd>
+ Makes a table where the key/values are the values and value counts of the sequence.
+ This version works with &lsquo;hashable&rsquo; values like strings and numbers.
+ <a href="../libraries/pl.tablex.html#count_map">pl.tablex.count_map</a> is more general.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ a map-like table</li>
+ <li>
+ a table</li>
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#count_map">pl.tablex.count_map</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "printall"></a>
+ <strong>printall (iter, sep, nfields, fmt)</strong>
+ </dt>
+ <dd>
+ print out a sequence iter with a separator.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ <li><span class="parameter">sep</span>
+ the separator (default space)
+ </li>
+ <li><span class="parameter">nfields</span>
+ maximum number of values per line (default 7)
+ </li>
+ <li><span class="parameter">fmt</span>
+ optional format function for each value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "map"></a>
+ <strong>map (fn, iter, arg)</strong>
+ </dt>
+ <dd>
+ return a sequence where every element of a sequence has been transformed
+ by a function. If you don&rsquo;t supply an argument, then the function will
+ receive both values of a double-valued sequence, otherwise behaves rather like
+ tablex.map.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fn</span>
+ a function to apply to elements; may take two arguments
+ </li>
+ <li><span class="parameter">iter</span>
+ a sequence of one or two values
+ </li>
+ <li><span class="parameter">arg</span>
+ optional argument to pass to function.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "filter"></a>
+ <strong>filter (iter, pred, arg)</strong>
+ </dt>
+ <dd>
+ filter a sequence using a predicate function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence of one or two values
+ </li>
+ <li><span class="parameter">pred</span>
+ a boolean function; may take two arguments
+ </li>
+ <li><span class="parameter">arg</span>
+ optional argument to pass to function.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "reduce"></a>
+ <strong>reduce (fn, iter, initval)</strong>
+ </dt>
+ <dd>
+ &lsquo;reduce&rsquo; a sequence using a binary function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fn</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of two arguments
+ </li>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ <li><span class="parameter">initval</span>
+ optional initial value
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">seq.reduce(operator.add,seq.list{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>}) == <span class="number">10</span></pre></li>
+ <li><pre class="example">seq.reduce(<span class="string">'-'</span>,{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}) == -<span class="number">13</span></pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "take"></a>
+ <strong>take (iter, n)</strong>
+ </dt>
+ <dd>
+ take the first n values from the sequence.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence of one or two values
+ </li>
+ <li><span class="parameter">n</span>
+ number of items to take
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a sequence of at most n items
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "skip"></a>
+ <strong>skip (iter, n)</strong>
+ </dt>
+ <dd>
+ skip the first n values of a sequence
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence of one or more values
+ </li>
+ <li><span class="parameter">n</span>
+ number of items to skip
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "enum"></a>
+ <strong>enum (iter)</strong>
+ </dt>
+ <dd>
+ a sequence with a sequence count and the original value.
+ enum(copy(ls)) is a roundabout way of saying ipairs(ls).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a single or double valued sequence
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ sequence of (i,v), i = 1..n and v is from iter.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "mapmethod"></a>
+ <strong>mapmethod (iter, name, arg1, arg2)</strong>
+ </dt>
+ <dd>
+ map using a named method over a sequence.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ <li><span class="parameter">name</span>
+ the method name
+ </li>
+ <li><span class="parameter">arg1</span>
+ optional first extra argument
+ </li>
+ <li><span class="parameter">arg2</span>
+ optional second extra argument
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "last"></a>
+ <strong>last (iter)</strong>
+ </dt>
+ <dd>
+ a sequence of (last,current) values from another sequence.
+ This will return S(i-1),S(i) if given S(i)
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "foreach"></a>
+ <strong>foreach (iter, fn)</strong>
+ </dt>
+ <dd>
+ call the function on each element of the sequence.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">iter</span>
+ a sequence with up to 3 values
+ </li>
+ <li><span class="parameter">fn</span>
+ a function
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "lines"></a>
+ <strong>lines (f, ...)</strong>
+ </dt>
+ <dd>
+ create a wrapped iterator over all lines in the file.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ either a filename, file-like object, or &lsquo;STDIN&rsquo; (for standard input)
+ </li>
+ <li><span class="parameter">...</span>
+ for Lua 5.2 only, optional format specifiers, as in <a href="https://www.lua.org/manual/5.1/manual.html#pdf-io.read">io.read</a>.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a sequence wrapper
+ </ol>
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.sip.html b/docs/libraries/pl.sip.html
new file mode 100644
index 0000000..9a5d913
--- /dev/null
+++ b/docs/libraries/pl.sip.html
@@ -0,0 +1,400 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><strong>pl.sip</strong></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.sip</code></h1>
+<p>Simple Input Patterns (SIP).</p>
+<p> SIP patterns start with &lsquo;$&rsquo;, then a
+ one-letter type, and then an optional variable in curly braces.</p>
+
+<pre>
+sip.match(<span class="string">'$v=$q'</span>,<span class="string">'name="dolly"'</span>,res)
+==&gt; res=={<span class="string">'name'</span>,<span class="string">'dolly'</span>}
+sip.match(<span class="string">'($q{first},$q{second})'</span>,<span class="string">'("john","smith")'</span>,res)
+==&gt; res=={second=<span class="string">'smith'</span>,first=<span class="string">'john'</span>}
+</pre>
+
+
+<p> Type names:</p>
+
+<pre>
+v identifier
+i integer
+f floating-point
+q quoted <span class="global">string</span>
+([{&lt; match up to closing bracket
+</pre>
+
+
+<p> See <a href="../manual/08-additional.md.html#Simple_Input_Patterns">the Guide</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#create_pattern">create_pattern (spec, options)</a></td>
+ <td class="summary">convert a SIP pattern into the equivalent Lua string pattern.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#compile">compile (spec, options)</a></td>
+ <td class="summary">convert a SIP pattern into a matching function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#match">match (spec, line, res, options)</a></td>
+ <td class="summary">match a SIP pattern against a string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#match_at_start">match_at_start (spec, line, res)</a></td>
+ <td class="summary">match a SIP pattern against the start of a string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#fields">fields (spec, f)</a></td>
+ <td class="summary">given a pattern and a file object, return an iterator over the results</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pattern">pattern (spec, fun)</a></td>
+ <td class="summary">register a match which will be used in the read function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#read">read (f, matches)</a></td>
+ <td class="summary">enter a loop which applies all registered matches to the input file.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "create_pattern"></a>
+ <strong>create_pattern (spec, options)</strong>
+ </dt>
+ <dd>
+ convert a SIP pattern into the equivalent Lua string pattern.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">spec</span>
+ a SIP pattern
+ </li>
+ <li><span class="parameter">options</span>
+ a table; only the <code>at_start</code> field is
+ currently meaningful and ensures that the pattern is anchored
+ at the start of the string.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a Lua string pattern.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "compile"></a>
+ <strong>compile (spec, options)</strong>
+ </dt>
+ <dd>
+ convert a SIP pattern into a matching function.
+ The returned function takes two arguments, the line and an empty table.
+ If the line matched the pattern, then this function returns true
+ and the table is filled with field-value pairs.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">spec</span>
+ a SIP pattern
+ </li>
+ <li><span class="parameter">options</span>
+ optional table; {at_start=true} ensures that the pattern
+ is anchored at the start of the string.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function if successful, or nil,error
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "match"></a>
+ <strong>match (spec, line, res, options)</strong>
+ </dt>
+ <dd>
+ match a SIP pattern against a string.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">spec</span>
+ a SIP pattern
+ </li>
+ <li><span class="parameter">line</span>
+ a string
+ </li>
+ <li><span class="parameter">res</span>
+ a table to receive values
+ </li>
+ <li><span class="parameter">options</span>
+ (optional) option table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or false
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "match_at_start"></a>
+ <strong>match_at_start (spec, line, res)</strong>
+ </dt>
+ <dd>
+ match a SIP pattern against the start of a string.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">spec</span>
+ a SIP pattern
+ </li>
+ <li><span class="parameter">line</span>
+ a string
+ </li>
+ <li><span class="parameter">res</span>
+ a table to receive values
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or false
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "fields"></a>
+ <strong>fields (spec, f)</strong>
+ </dt>
+ <dd>
+ given a pattern and a file object, return an iterator over the results
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">spec</span>
+ a SIP pattern
+ </li>
+ <li><span class="parameter">f</span>
+ a file-like object.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "pattern"></a>
+ <strong>pattern (spec, fun)</strong>
+ </dt>
+ <dd>
+ register a match which will be used in the read function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">spec</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a SIP pattern
+ </li>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function to be called with the results of the match
+ </li>
+ </ul>
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.sip.html#read">read</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "read"></a>
+ <strong>read (f, matches)</strong>
+ </dt>
+ <dd>
+ enter a loop which applies all registered matches to the input file.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a file-like object
+ </li>
+ <li><span class="parameter">matches</span>
+ <span class="types"><span class="type">array</span></span>
+ optional list of <code>{spec,fun}</code> pairs, as for <a href="../libraries/pl.sip.html#pattern">pattern</a> above.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.strict.html b/docs/libraries/pl.strict.html
new file mode 100644
index 0000000..79f9b34
--- /dev/null
+++ b/docs/libraries/pl.strict.html
@@ -0,0 +1,254 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><strong>pl.strict</strong></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.strict</code></h1>
+<p>Checks uses of undeclared global variables.</p>
+<p> All global variables must be &lsquo;declared&rsquo; through a regular assignment
+ (even assigning <code>nil</code> will do) in a main chunk before being used
+ anywhere or assigned to inside a function. Existing metatables <code>__newindex</code> and <code>__index</code>
+ metamethods are respected.</p>
+
+<p> You can set any table to have strict behaviour using <a href="../libraries/pl.strict.html#module">strict.module</a>. Creating a new
+ module with <a href="../libraries/pl.strict.html#closed_module">strict.closed_module</a> makes the module immune to monkey-patching, if
+ you don&rsquo;t wish to encourage monkey business.</p>
+
+<p> If the global <code>PENLIGHT_NO_GLOBAL_STRICT</code> is defined, then this module won&rsquo;t make the
+ global environment strict - if you just want to explicitly set table strictness.</p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#module">module (name[, mod[, predeclared]])</a></td>
+ <td class="summary">make an existing table strict.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#make_all_strict">make_all_strict (T)</a></td>
+ <td class="summary">make all tables in a table strict.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#closed_module">closed_module (mod, name)</a></td>
+ <td class="summary">make a new module table which is closed to further changes.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "module"></a>
+ <strong>module (name[, mod[, predeclared]])</strong>
+ </dt>
+ <dd>
+ make an existing table strict.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">name</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ name of table (optional)
+ </li>
+ <li><span class="parameter">mod</span>
+ <span class="types"><span class="type">tab</span></span>
+ table - if <code>nil</code> then we&rsquo;ll return a new table
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">predeclared</span>
+ <span class="types"><span class="type">tab</span></span>
+ <ul>
+<li>table of variables that are to be considered predeclared.</li>
+</ul>
+
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the given table, or a new table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "make_all_strict"></a>
+ <strong>make_all_strict (T)</strong>
+ </dt>
+ <dd>
+ make all tables in a table strict.
+ So <code>strict.make_all_strict(_G)</code> prevents monkey-patching
+ of any global table
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">T</span>
+ <span class="types"><span class="type">tab</span></span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "closed_module"></a>
+ <strong>closed_module (mod, name)</strong>
+ </dt>
+ <dd>
+ make a new module table which is closed to further changes.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">mod</span>
+
+ </li>
+ <li><span class="parameter">name</span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.stringio.html b/docs/libraries/pl.stringio.html
new file mode 100644
index 0000000..ca903fa
--- /dev/null
+++ b/docs/libraries/pl.stringio.html
@@ -0,0 +1,216 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><strong>pl.stringio</strong></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.stringio</code></h1>
+<p>Reading and writing strings using file-like objects.</p>
+<p> <br></p>
+
+<pre>
+f = stringio.open(text)
+l1 = f:read() <span class="comment">-- read first line
+</span>n,m = f:read (<span class="string">'*n'</span>,<span class="string">'*n'</span>) <span class="comment">-- read two numbers
+</span><span class="keyword">for</span> line <span class="keyword">in</span> f:lines() <span class="keyword">do</span> <span class="global">print</span>(line) <span class="keyword">end</span> <span class="comment">-- iterate over all lines
+</span>f = stringio.create()
+f:write(<span class="string">'hello'</span>)
+f:write(<span class="string">'dolly'</span>)
+<span class="global">assert</span>(f:value(),<span class="string">'hellodolly'</span>)
+</pre>
+
+
+<p> See <a href="../manual/03-strings.md.html#File_style_I_O_on_Strings">the Guide</a>.</p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#create">create ()</a></td>
+ <td class="summary">create a file-like object which can be used to construct a string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#open">open (s)</a></td>
+ <td class="summary">create a file-like object for reading from a given string.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "create"></a>
+ <strong>create ()</strong>
+ </dt>
+ <dd>
+ create a file-like object which can be used to construct a string.
+ The resulting object has an extra <code>value()</code> method for
+ retrieving the string value. Implements <a href="../libraries/pl.file.html#write">file:write</a>, <code>file:seek</code>, <code>file:lines</code>,
+ plus an extra <code>writef</code> method which works like <a href="../libraries/pl.utils.html#printf">utils.printf</a>.
+
+
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">f = create(); f:write(<span class="string">'hello, dolly\n'</span>); <span class="global">print</span>(f:value())</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "open"></a>
+ <strong>open (s)</strong>
+ </dt>
+ <dd>
+ create a file-like object for reading from a given string.
+ Implements <a href="../libraries/pl.file.html#read">file:read</a>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ The input string.
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">fs = open <span class="string">'20 10'</span>; x,y = f:read (<span class="string">'*n'</span>,<span class="string">'*n'</span>); <span class="global">assert</span>(x == <span class="number">20</span> <span class="keyword">and</span> y == <span class="number">10</span>)</pre>
+ </ul>
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.stringx.html b/docs/libraries/pl.stringx.html
new file mode 100644
index 0000000..666a958
--- /dev/null
+++ b/docs/libraries/pl.stringx.html
@@ -0,0 +1,1162 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#String_Predicates">String Predicates </a></li>
+<li><a href="#Strings_and_Lists">Strings and Lists </a></li>
+<li><a href="#Finding_and_Replacing">Finding and Replacing </a></li>
+<li><a href="#Stripping_and_Justifying">Stripping and Justifying </a></li>
+<li><a href="#Partioning_Strings">Partioning Strings </a></li>
+<li><a href="#Miscelaneous">Miscelaneous </a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><strong>pl.stringx</strong></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.stringx</code></h1>
+<p>Python-style extended string library.</p>
+<p> see 3.6.1 of the Python reference.
+ If you want to make these available as string methods, then say
+ <code>stringx.import()</code> to bring them into the standard <a href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> table.</p>
+
+<p> See <a href="../manual/03-strings.md.html#">the Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a></p>
+
+
+<h2><a href="#String_Predicates">String Predicates </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#isalpha">isalpha (s)</a></td>
+ <td class="summary">does s only contain alphabetic characters?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isdigit">isdigit (s)</a></td>
+ <td class="summary">does s only contain digits?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isalnum">isalnum (s)</a></td>
+ <td class="summary">does s only contain alphanumeric characters?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isspace">isspace (s)</a></td>
+ <td class="summary">does s only contain spaces?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#islower">islower (s)</a></td>
+ <td class="summary">does s only contain lower case characters?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#isupper">isupper (s)</a></td>
+ <td class="summary">does s only contain upper case characters?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#startswith">startswith (s, prefix)</a></td>
+ <td class="summary">does s start with prefix or one of prefixes?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#endswith">endswith (s, suffix)</a></td>
+ <td class="summary">does s end with suffix or one of suffixes?</td>
+ </tr>
+</table>
+<h2><a href="#Strings_and_Lists">Strings and Lists </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#join">join (s, seq)</a></td>
+ <td class="summary">concatenate the strings using this string as a delimiter.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#splitlines">splitlines (s[, keep_ends])</a></td>
+ <td class="summary">Split a string into a list of lines.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#split">split (s[, re[, n]])</a></td>
+ <td class="summary">split a string into a list of strings using a delimiter.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#expandtabs">expandtabs (s, tabsize)</a></td>
+ <td class="summary">replace all tabs in s with tabsize spaces.</td>
+ </tr>
+</table>
+<h2><a href="#Finding_and_Replacing">Finding and Replacing </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#lfind">lfind (s, sub[, first[, last]])</a></td>
+ <td class="summary">find index of first instance of sub in s from the left.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#rfind">rfind (s, sub[, first[, last]])</a></td>
+ <td class="summary">find index of first instance of sub in s from the right.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#replace">replace (s, old, new[, n])</a></td>
+ <td class="summary">replace up to n instances of old by new in the string s.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#count">count (s, sub)</a></td>
+ <td class="summary">count all instances of substring in string.</td>
+ </tr>
+</table>
+<h2><a href="#Stripping_and_Justifying">Stripping and Justifying </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#ljust">ljust (s, w[, ch=' '])</a></td>
+ <td class="summary">left-justify s with width w.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#rjust">rjust (s, w[, ch=' '])</a></td>
+ <td class="summary">right-justify s with width w.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#center">center (s, w[, ch=' '])</a></td>
+ <td class="summary">center-justify s with width w.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#lstrip">lstrip (s[, chrs='%s'])</a></td>
+ <td class="summary">trim any whitespace on the left of s.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#rstrip">rstrip (s[, chrs='%s'])</a></td>
+ <td class="summary">trim any whitespace on the right of s.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#strip">strip (s[, chrs='%s'])</a></td>
+ <td class="summary">trim any whitespace on both left and right of s.</td>
+ </tr>
+</table>
+<h2><a href="#Partioning_Strings">Partioning Strings </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#splitv">splitv (s[, re='%s'])</a></td>
+ <td class="summary">split a string using a pattern.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#partition">partition (s, ch)</a></td>
+ <td class="summary">partition the string using first occurance of a delimiter</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#rpartition">rpartition (s, ch)</a></td>
+ <td class="summary">partition the string p using last occurance of a delimiter</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#at">at (s, idx)</a></td>
+ <td class="summary">return the &lsquo;character&rsquo; at the index.</td>
+ </tr>
+</table>
+<h2><a href="#Miscelaneous">Miscelaneous </a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#lines">lines (s)</a></td>
+ <td class="summary">return an iterator over all lines in a string</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#title">title (s)</a></td>
+ <td class="summary">iniital word letters uppercase (&lsquo;title case&rsquo;).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#shorten">shorten (s, w, tail)</a></td>
+ <td class="summary">Return a shortened version of a string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#quote_string">quote_string (s)</a></td>
+ <td class="summary">Quote the given string and preserve any control or escape characters, such that reloading the string in Lua returns the same result.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="String_Predicates"></a>String Predicates </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "isalpha"></a>
+ <strong>isalpha (s)</strong>
+ </dt>
+ <dd>
+ does s only contain alphabetic characters?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isdigit"></a>
+ <strong>isdigit (s)</strong>
+ </dt>
+ <dd>
+ does s only contain digits?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isalnum"></a>
+ <strong>isalnum (s)</strong>
+ </dt>
+ <dd>
+ does s only contain alphanumeric characters?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isspace"></a>
+ <strong>isspace (s)</strong>
+ </dt>
+ <dd>
+ does s only contain spaces?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "islower"></a>
+ <strong>islower (s)</strong>
+ </dt>
+ <dd>
+ does s only contain lower case characters?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "isupper"></a>
+ <strong>isupper (s)</strong>
+ </dt>
+ <dd>
+ does s only contain upper case characters?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "startswith"></a>
+ <strong>startswith (s, prefix)</strong>
+ </dt>
+ <dd>
+ does s start with prefix or one of prefixes?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string
+ </li>
+ <li><span class="parameter">prefix</span>
+ a string or an array of strings
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "endswith"></a>
+ <strong>endswith (s, suffix)</strong>
+ </dt>
+ <dd>
+ does s end with suffix or one of suffixes?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a string
+ </li>
+ <li><span class="parameter">suffix</span>
+ a string or an array of strings
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Strings_and_Lists"></a>Strings and Lists </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "join"></a>
+ <strong>join (s, seq)</strong>
+ </dt>
+ <dd>
+ concatenate the strings using this string as a delimiter.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">seq</span>
+ a table of strings or numbers
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">(<span class="string">' '</span>):join {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} == <span class="string">'1 2 3'</span></pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "splitlines"></a>
+ <strong>splitlines (s[, keep_ends])</strong>
+ </dt>
+ <dd>
+ Split a string into a list of lines.
+ <code>&quot;\r&quot;</code>, <code>&quot;\n&quot;</code>, and <code>&quot;\r\n&quot;</code> are considered line ends.
+ They are not included in the lines unless <code>keepends</code> is passed.
+ Terminal line end does not produce an extra line.
+ Splitting an empty string results in an empty list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string.
+ </li>
+ <li><span class="parameter">keep_ends</span>
+ <span class="types"><span class="type">bool</span></span>
+ include line ends.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "split"></a>
+ <strong>split (s[, re[, n]])</strong>
+ </dt>
+ <dd>
+ split a string into a list of strings using a delimiter.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">re</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a delimiter (defaults to whitespace)
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">n</span>
+ <span class="types"><span class="type">int</span></span>
+ maximum number of results
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">#((<span class="string">'one two'</span>):split()) == <span class="number">2</span></pre></li>
+ <li><pre class="example">(<span class="string">'one,two,three'</span>):split(<span class="string">','</span>) == List{<span class="string">'one'</span>,<span class="string">'two'</span>,<span class="string">'three'</span>}</pre></li>
+ <li><pre class="example">(<span class="string">'one,two,three'</span>):split(<span class="string">','</span>,<span class="number">2</span>) == List{<span class="string">'one'</span>,<span class="string">'two,three'</span>}</pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "expandtabs"></a>
+ <strong>expandtabs (s, tabsize)</strong>
+ </dt>
+ <dd>
+ replace all tabs in s with tabsize spaces. If not specified, tabsize defaults to 8.
+ with 0.9.5 this now correctly expands to the next tab stop (if you really
+ want to just replace tabs, use :gsub(&lsquo;\t&rsquo;,&lsquo; &rsquo;) etc)
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">tabsize</span>
+ <span class="types"><span class="type">int</span></span>
+ [opt=8] number of spaces to expand each tab
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Finding_and_Replacing"></a>Finding and Replacing </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "lfind"></a>
+ <strong>lfind (s, sub[, first[, last]])</strong>
+ </dt>
+ <dd>
+ find index of first instance of sub in s from the left.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">sub</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ substring
+ </li>
+ <li><span class="parameter">first</span>
+ <span class="types"><span class="type">int</span></span>
+ first index
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">last</span>
+ <span class="types"><span class="type">int</span></span>
+ last index
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "rfind"></a>
+ <strong>rfind (s, sub[, first[, last]])</strong>
+ </dt>
+ <dd>
+ find index of first instance of sub in s from the right.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">sub</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ substring
+ </li>
+ <li><span class="parameter">first</span>
+ <span class="types"><span class="type">int</span></span>
+ first index
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">last</span>
+ <span class="types"><span class="type">int</span></span>
+ last index
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "replace"></a>
+ <strong>replace (s, old, new[, n])</strong>
+ </dt>
+ <dd>
+ replace up to n instances of old by new in the string s.
+ if n is not present, replace all instances.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">old</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the target substring
+ </li>
+ <li><span class="parameter">new</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the substitution
+ </li>
+ <li><span class="parameter">n</span>
+ <span class="types"><span class="type">int</span></span>
+ optional maximum number of substitutions
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ result string
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "count"></a>
+ <strong>count (s, sub)</strong>
+ </dt>
+ <dd>
+ count all instances of substring in string.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">sub</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ substring
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Stripping_and_Justifying"></a>Stripping and Justifying </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "ljust"></a>
+ <strong>ljust (s, w[, ch=' '])</strong>
+ </dt>
+ <dd>
+ left-justify s with width w.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">w</span>
+ <span class="types"><span class="type">int</span></span>
+ width of justification
+ </li>
+ <li><span class="parameter">ch</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ padding character
+ (<em>default</em> ' ')
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "rjust"></a>
+ <strong>rjust (s, w[, ch=' '])</strong>
+ </dt>
+ <dd>
+ right-justify s with width w.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">w</span>
+ <span class="types"><span class="type">int</span></span>
+ width of justification
+ </li>
+ <li><span class="parameter">ch</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ padding character
+ (<em>default</em> ' ')
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "center"></a>
+ <strong>center (s, w[, ch=' '])</strong>
+ </dt>
+ <dd>
+ center-justify s with width w.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">w</span>
+ <span class="types"><span class="type">int</span></span>
+ width of justification
+ </li>
+ <li><span class="parameter">ch</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ padding character
+ (<em>default</em> ' ')
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "lstrip"></a>
+ <strong>lstrip (s[, chrs='%s'])</strong>
+ </dt>
+ <dd>
+ trim any whitespace on the left of s.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">chrs</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ default any whitespace character,
+ but can be a string of characters to be trimmed
+ (<em>default</em> '%s')
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "rstrip"></a>
+ <strong>rstrip (s[, chrs='%s'])</strong>
+ </dt>
+ <dd>
+ trim any whitespace on the right of s.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">chrs</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ default any whitespace character,
+ but can be a string of characters to be trimmed
+ (<em>default</em> '%s')
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "strip"></a>
+ <strong>strip (s[, chrs='%s'])</strong>
+ </dt>
+ <dd>
+ trim any whitespace on both left and right of s.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">chrs</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ default any whitespace character,
+ but can be a string of characters to be trimmed
+ (<em>default</em> '%s')
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Partioning_Strings"></a>Partioning Strings </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "splitv"></a>
+ <strong>splitv (s[, re='%s'])</strong>
+ </dt>
+ <dd>
+ split a string using a pattern. Note that at least one value will be returned!
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">re</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a Lua string pattern (defaults to whitespace)
+ (<em>default</em> '%s')
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the parts of the string
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">a,b = line:splitv(<span class="string">'='</span>)</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "partition"></a>
+ <strong>partition (s, ch)</strong>
+ </dt>
+ <dd>
+ partition the string using first occurance of a delimiter
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">ch</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ delimiter
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ part before ch</li>
+ <li>
+ ch</li>
+ <li>
+ part after ch</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "rpartition"></a>
+ <strong>rpartition (s, ch)</strong>
+ </dt>
+ <dd>
+ partition the string p using last occurance of a delimiter
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">ch</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ delimiter
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ part before ch</li>
+ <li>
+ ch</li>
+ <li>
+ part after ch</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "at"></a>
+ <strong>at (s, idx)</strong>
+ </dt>
+ <dd>
+ return the &lsquo;character&rsquo; at the index.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">idx</span>
+ <span class="types"><span class="type">int</span></span>
+ an index (can be negative)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a substring of length 1 if successful, empty string otherwise.
+ </ol>
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Miscelaneous"></a>Miscelaneous </h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "lines"></a>
+ <strong>lines (s)</strong>
+ </dt>
+ <dd>
+ return an iterator over all lines in a string
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an iterator
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "title"></a>
+ <strong>title (s)</strong>
+ </dt>
+ <dd>
+ iniital word letters uppercase (&lsquo;title case&rsquo;).
+ Here &lsquo;words&rsquo; mean chunks of non-space characters.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string with each word&rsquo;s first letter uppercase
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "shorten"></a>
+ <strong>shorten (s, w, tail)</strong>
+ </dt>
+ <dd>
+ Return a shortened version of a string.
+ Fits string within w characters. Removed characters are marked with ellipsis.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">w</span>
+ <span class="types"><span class="type">int</span></span>
+ the maxinum size allowed
+ </li>
+ <li><span class="parameter">tail</span>
+ <span class="types"><span class="type">bool</span></span>
+ true if we want to show the end of the string (head otherwise)
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">(<span class="string">'1234567890'</span>):shorten(<span class="number">8</span>) == <span class="string">'12345...'</span></pre></li>
+ <li><pre class="example">(<span class="string">'1234567890'</span>):shorten(<span class="number">8</span>, <span class="keyword">true</span>) == <span class="string">'...67890'</span></pre></li>
+ <li><pre class="example">(<span class="string">'1234567890'</span>):shorten(<span class="number">20</span>) == <span class="string">'1234567890'</span></pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "quote_string"></a>
+ <strong>quote_string (s)</strong>
+ </dt>
+ <dd>
+ Quote the given string and preserve any control or escape characters, such that reloading the string in Lua returns the same result.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ The string to be quoted.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ The quoted string.
+ </ol>
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.tablex.html b/docs/libraries/pl.tablex.html
new file mode 100644
index 0000000..ded9185
--- /dev/null
+++ b/docs/libraries/pl.tablex.html
@@ -0,0 +1,1895 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+<li><a href="#Copying">Copying</a></li>
+<li><a href="#Comparing">Comparing</a></li>
+<li><a href="#Finding">Finding</a></li>
+<li><a href="#MappingAndFiltering">MappingAndFiltering</a></li>
+<li><a href="#Iterating">Iterating</a></li>
+<li><a href="#Extraction">Extraction</a></li>
+<li><a href="#Merging">Merging</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><strong>pl.tablex</strong></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.tablex</code></h1>
+<p>Extended operations on Lua tables.</p>
+<p> See <a href="../manual/02-arrays.md.html#Useful_Operations_on_Tables">the Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.types.html#">pl.types</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#size">size (t)</a></td>
+ <td class="summary">total number of elements in this table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#index_by">index_by (tbl, idx)</a></td>
+ <td class="summary">return a list of all values in a table indexed by another list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#transform">transform (fun, t, ...)</a></td>
+ <td class="summary">apply a function to all values of a table, in-place.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#range">range (start, finish[, step=1])</a></td>
+ <td class="summary">generate a table of all numbers in a range.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#reduce">reduce (fun, t, memo)</a></td>
+ <td class="summary">&lsquo;reduce&rsquo; a list using a binary function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#index_map">index_map (t)</a></td>
+ <td class="summary">create an index map from a list-like table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#makeset">makeset (t)</a></td>
+ <td class="summary">create a set from a list-like table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#union">union (t1, t2)</a></td>
+ <td class="summary">the union of two map-like tables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#intersection">intersection (t1, t2)</a></td>
+ <td class="summary">the intersection of two map-like tables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#count_map">count_map (t, cmp)</a></td>
+ <td class="summary">A table where the key/values are the values and value counts of the table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#set">set (t, val[, i1=1[, i2=#t]])</a></td>
+ <td class="summary">set an array range to a value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#new">new (n, val)</a></td>
+ <td class="summary">create a new array of specified size with initial value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#clear">clear (t, istart)</a></td>
+ <td class="summary">clear out the contents of a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#removevalues">removevalues (t, i1, i2)</a></td>
+ <td class="summary">remove a range of values from a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#readonly">readonly (t)</a></td>
+ <td class="summary">modifies a table to be read only.</td>
+ </tr>
+</table>
+<h2><a href="#Copying">Copying</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#update">update (t1, t2)</a></td>
+ <td class="summary">copy a table into another, in-place.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#copy">copy (t)</a></td>
+ <td class="summary">make a shallow copy of a table</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#deepcopy">deepcopy (t)</a></td>
+ <td class="summary">make a deep copy of a table, recursively copying all the keys and fields.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#icopy">icopy (dest, src[, idest=1[, isrc=1[, nsrc=#src]]])</a></td>
+ <td class="summary">copy an array into another one, clearing <code>dest</code> after <code>idest+nsrc</code>, if necessary.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#move">move (dest, src[, idest=1[, isrc=1[, nsrc=#src]]])</a></td>
+ <td class="summary">copy an array into another one.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#insertvalues">insertvalues (t[, position], values)</a></td>
+ <td class="summary">insert values into a table.</td>
+ </tr>
+</table>
+<h2><a href="#Comparing">Comparing</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#deepcompare">deepcompare (t1, t2[, ignore_mt[, eps]])</a></td>
+ <td class="summary">compare two values.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#compare">compare (t1, t2, cmp)</a></td>
+ <td class="summary">compare two arrays using a predicate.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#compare_no_order">compare_no_order (t1, t2, cmp)</a></td>
+ <td class="summary">compare two list-like tables using an optional predicate, without regard for element order.</td>
+ </tr>
+</table>
+<h2><a href="#Finding">Finding</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#find">find (t, val, idx)</a></td>
+ <td class="summary">return the index of a value in a list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#rfind">rfind (t, val, idx)</a></td>
+ <td class="summary">return the index of a value in a list, searching from the end.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#find_if">find_if (t, cmp, arg)</a></td>
+ <td class="summary">return the index (or key) of a value in a table using a comparison function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#search">search (t, value[, exclude])</a></td>
+ <td class="summary">find a value in a table by recursive search.</td>
+ </tr>
+</table>
+<h2><a href="#MappingAndFiltering">MappingAndFiltering</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#map">map (fun, t, ...)</a></td>
+ <td class="summary">apply a function to all values of a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#imap">imap (fun, t, ...)</a></td>
+ <td class="summary">apply a function to all values of a list.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#map_named_method">map_named_method (name, t, ...)</a></td>
+ <td class="summary">apply a named method to values from a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#map2">map2 (fun, t1, t2, ...)</a></td>
+ <td class="summary">apply a function to values from two tables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#imap2">imap2 (fun, t1, t2, ...)</a></td>
+ <td class="summary">apply a function to values from two arrays.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#mapn">mapn (fun, ..., fun)</a></td>
+ <td class="summary">Apply a function to a number of tables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#pairmap">pairmap (fun, t, ...)</a></td>
+ <td class="summary">call the function with the key and value pairs from a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#filter">filter (t, pred, arg)</a></td>
+ <td class="summary">filter an array&rsquo;s values using a predicate function</td>
+ </tr>
+</table>
+<h2><a href="#Iterating">Iterating</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#foreach">foreach (t, fun, ...)</a></td>
+ <td class="summary">apply a function to all elements of a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#foreachi">foreachi (t, fun, ...)</a></td>
+ <td class="summary">apply a function to all elements of a list-like table in order.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#sort">sort (t, f)</a></td>
+ <td class="summary">return an iterator to a table sorted by its keys</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#sortv">sortv (t, f)</a></td>
+ <td class="summary">return an iterator to a table sorted by its values</td>
+ </tr>
+</table>
+<h2><a href="#Extraction">Extraction</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#keys">keys (t)</a></td>
+ <td class="summary">return all the keys of a table in arbitrary order.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#values">values (t)</a></td>
+ <td class="summary">return all the values of the table in arbitrary order</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#sub">sub (t, first, last)</a></td>
+ <td class="summary">Extract a range from a table, like &lsquo;string.sub&rsquo;.</td>
+ </tr>
+</table>
+<h2><a href="#Merging">Merging</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#merge">merge (t1, t2, dup)</a></td>
+ <td class="summary">combine two tables, either as union or intersection.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#difference">difference (s1, s2, symm)</a></td>
+ <td class="summary">a new table which is the difference of two tables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#zip">zip (...)</a></td>
+ <td class="summary">return a table where each element is a table of the ith values of an arbitrary
+ number of tables.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "size"></a>
+ <strong>size (t)</strong>
+ </dt>
+ <dd>
+ total number of elements in this table.
+ Note that this is distinct from <code>#t</code>, which is the number
+ of values in the array part; this value will always
+ be greater or equal. The difference gives the size of
+ the hash part, for practical purposes. Works for any
+ object with a __pairs metamethod.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the size
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "index_by"></a>
+ <strong>index_by (tbl, idx)</strong>
+ </dt>
+ <dd>
+ return a list of all values in a table indexed by another list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tbl</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">idx</span>
+ <span class="types"><span class="type">array</span></span>
+ an index table (a list of keys)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list-like table
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">index_by({<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>},{<span class="number">2</span>,<span class="number">4</span>}) == {<span class="number">20</span>,<span class="number">40</span>}</pre></li>
+ <li><pre class="example">index_by({one=<span class="number">1</span>,two=<span class="number">2</span>,three=<span class="number">3</span>},{<span class="string">'one'</span>,<span class="string">'three'</span>}) == {<span class="number">1</span>,<span class="number">3</span>}</pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "transform"></a>
+ <strong>transform (fun, t, ...)</strong>
+ </dt>
+ <dd>
+ apply a function to all values of a table, in-place.
+ Any extra arguments are passed to the function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ A function that takes at least one argument
+ </li>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">...</span>
+ extra arguments
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "range"></a>
+ <strong>range (start, finish[, step=1])</strong>
+ </dt>
+ <dd>
+ generate a table of all numbers in a range.
+ This is consistent with a numerical for loop.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">start</span>
+ <span class="types"><span class="type">int</span></span>
+ number
+ </li>
+ <li><span class="parameter">finish</span>
+ <span class="types"><span class="type">int</span></span>
+ number
+ </li>
+ <li><span class="parameter">step</span>
+ <span class="types"><span class="type">int</span></span>
+ make this negative for start &lt; finish
+ (<em>default</em> 1)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "reduce"></a>
+ <strong>reduce (fun, t, memo)</strong>
+ </dt>
+ <dd>
+ &lsquo;reduce&rsquo; a list using a binary function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of two arguments
+ </li>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">memo</span>
+ <span class="types"><span class="type">array</span></span>
+ optional initial memo value. Defaults to first value in table.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the result of the function
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">reduce(<span class="string">'+'</span>,{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>}) == <span class="number">10</span></pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "index_map"></a>
+ <strong>index_map (t)</strong>
+ </dt>
+ <dd>
+ create an index map from a list-like table. The original values become keys,
+ and the associated values are the indices into the original list.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a map-like table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "makeset"></a>
+ <strong>makeset (t)</strong>
+ </dt>
+ <dd>
+ create a set from a list-like table. A set is a table where the original values
+ become keys, and the associated values are all true.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a set (a map-like table)
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "union"></a>
+ <strong>union (t1, t2)</strong>
+ </dt>
+ <dd>
+ the union of two map-like tables.
+ If there are duplicate keys, the second table wins.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><span class="type">tab</span></span>
+
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#merge">tablex.merge</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "intersection"></a>
+ <strong>intersection (t1, t2)</strong>
+ </dt>
+ <dd>
+ the intersection of two map-like tables.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <span class="types"><span class="type">tab</span></span>
+
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#merge">tablex.merge</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "count_map"></a>
+ <strong>count_map (t, cmp)</strong>
+ </dt>
+ <dd>
+ A table where the key/values are the values and value counts of the table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">cmp</span>
+ <span class="types"><span class="type">func</span></span>
+ a function that defines equality (otherwise uses ==)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a map-like table
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.seq.html#count_map">seq.count_map</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "set"></a>
+ <strong>set (t, val[, i1=1[, i2=#t]])</strong>
+ </dt>
+ <dd>
+ set an array range to a value. If it&rsquo;s a function we use the result
+ of applying it to the indices.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">val</span>
+ a value
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start range
+ (<em>default</em> 1)
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end range
+ (<em>default</em> #t)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "new"></a>
+ <strong>new (n, val)</strong>
+ </dt>
+ <dd>
+ create a new array of specified size with initial value.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">n</span>
+ <span class="types"><span class="type">int</span></span>
+ size
+ </li>
+ <li><span class="parameter">val</span>
+ initial value (can be <code>nil</code>, but don&rsquo;t expect <code>#</code> to work!)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "clear"></a>
+ <strong>clear (t, istart)</strong>
+ </dt>
+ <dd>
+ clear out the contents of a table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list
+ </li>
+ <li><span class="parameter">istart</span>
+ optional start position
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "removevalues"></a>
+ <strong>removevalues (t, i1, i2)</strong>
+ </dt>
+ <dd>
+ remove a range of values from a table.
+ End of range may be negative.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">i1</span>
+ <span class="types"><span class="type">int</span></span>
+ start index
+ </li>
+ <li><span class="parameter">i2</span>
+ <span class="types"><span class="type">int</span></span>
+ end index
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "readonly"></a>
+ <strong>readonly (t)</strong>
+ </dt>
+ <dd>
+ modifies a table to be read only.
+ This only offers weak protection. Tables can still be modified with
+ <a href="https://www.lua.org/manual/5.1/manual.html#pdf-table.insert">table.insert</a> and <a href="https://www.lua.org/manual/5.1/manual.html#pdf-rawset">rawset</a>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ the table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the table read only.
+ </ol>
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Copying"></a>Copying</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "update"></a>
+ <strong>update (t1, t2)</strong>
+ </dt>
+ <dd>
+ copy a table into another, in-place.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">tab</span></span>
+ destination table
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">tab</span></span>
+ source (actually any iterable object)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ first table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "copy"></a>
+ <strong>copy (t)</strong>
+ </dt>
+ <dd>
+ make a shallow copy of a table
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ an iterable source
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ new table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "deepcopy"></a>
+ <strong>deepcopy (t)</strong>
+ </dt>
+ <dd>
+ make a deep copy of a table, recursively copying all the keys and fields.
+ This supports cycles in tables; cycles will be reproduced in the copy.
+ This will also set the copied table&rsquo;s metatable to that of the original.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ A table
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ new table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "icopy"></a>
+ <strong>icopy (dest, src[, idest=1[, isrc=1[, nsrc=#src]]])</strong>
+ </dt>
+ <dd>
+ copy an array into another one, clearing <code>dest</code> after <code>idest+nsrc</code>, if necessary.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">dest</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">src</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">idest</span>
+ <span class="types"><span class="type">int</span></span>
+ where to start copying values into destination
+ (<em>default</em> 1)
+ </li>
+ <li><span class="parameter">isrc</span>
+ <span class="types"><span class="type">int</span></span>
+ where to start copying values from source
+ (<em>default</em> 1)
+ </li>
+ <li><span class="parameter">nsrc</span>
+ <span class="types"><span class="type">int</span></span>
+ number of elements to copy from source
+ (<em>default</em> #src)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "move"></a>
+ <strong>move (dest, src[, idest=1[, isrc=1[, nsrc=#src]]])</strong>
+ </dt>
+ <dd>
+ copy an array into another one.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">dest</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">src</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">idest</span>
+ <span class="types"><span class="type">int</span></span>
+ where to start copying values into destination
+ (<em>default</em> 1)
+ </li>
+ <li><span class="parameter">isrc</span>
+ <span class="types"><span class="type">int</span></span>
+ where to start copying values from source
+ (<em>default</em> 1)
+ </li>
+ <li><span class="parameter">nsrc</span>
+ <span class="types"><span class="type">int</span></span>
+ number of elements to copy from source
+ (<em>default</em> #src)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "insertvalues"></a>
+ <strong>insertvalues (t[, position], values)</strong>
+ </dt>
+ <dd>
+ insert values into a table.
+ similar to <a href="https://www.lua.org/manual/5.1/manual.html#pdf-table.insert">table.insert</a> but inserts values from given table <a href="../libraries/pl.tablex.html#values">values</a>,
+ not the object itself, into table <code>t</code> at position <code>pos</code>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ the list
+ </li>
+ <li><span class="parameter">position</span>
+ <span class="types"><span class="type">int</span></span>
+ (default is at end)
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">values</span>
+ <span class="types"><span class="type">array</span></span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Comparing"></a>Comparing</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "deepcompare"></a>
+ <strong>deepcompare (t1, t2[, ignore_mt[, eps]])</strong>
+ </dt>
+ <dd>
+ compare two values.
+ if they are tables, then compare their keys and fields recursively.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t1</span>
+ A value
+ </li>
+ <li><span class="parameter">t2</span>
+ A value
+ </li>
+ <li><span class="parameter">ignore_mt</span>
+ <span class="types"><span class="type">bool</span></span>
+ if true, ignore __eq metamethod (default false)
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">eps</span>
+ <span class="types"><span class="type">number</span></span>
+ if defined, then used for any number comparisons
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true or false
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "compare"></a>
+ <strong>compare (t1, t2, cmp)</strong>
+ </dt>
+ <dd>
+ compare two arrays using a predicate.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">array</span></span>
+ an array
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">array</span></span>
+ an array
+ </li>
+ <li><span class="parameter">cmp</span>
+ <span class="types"><span class="type">func</span></span>
+ A comparison function
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "compare_no_order"></a>
+ <strong>compare_no_order (t1, t2, cmp)</strong>
+ </dt>
+ <dd>
+ compare two list-like tables using an optional predicate, without regard for element order.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">cmp</span>
+ A comparison function (may be nil)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Finding"></a>Finding</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "find"></a>
+ <strong>find (t, val, idx)</strong>
+ </dt>
+ <dd>
+ return the index of a value in a list.
+ Like string.find, there is an optional index to start searching,
+ which can be negative.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ A list-like table
+ </li>
+ <li><span class="parameter">val</span>
+ A value
+ </li>
+ <li><span class="parameter">idx</span>
+ <span class="types"><span class="type">int</span></span>
+ index to start; -1 means last element,etc (default 1)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ index of value or nil if not found
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">find({<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>},<span class="number">20</span>) == <span class="number">2</span></pre></li>
+ <li><pre class="example">find({<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'a'</span>,<span class="string">'c'</span>},<span class="string">'a'</span>,<span class="number">2</span>) == <span class="number">3</span></pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "rfind"></a>
+ <strong>rfind (t, val, idx)</strong>
+ </dt>
+ <dd>
+ return the index of a value in a list, searching from the end.
+ Like string.find, there is an optional index to start searching,
+ which can be negative.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ A list-like table
+ </li>
+ <li><span class="parameter">val</span>
+ A value
+ </li>
+ <li><span class="parameter">idx</span>
+ index to start; -1 means last element,etc (default 1)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ index of value or nil if not found
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">rfind({<span class="number">10</span>,<span class="number">10</span>,<span class="number">10</span>},<span class="number">10</span>) == <span class="number">3</span></pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "find_if"></a>
+ <strong>find_if (t, cmp, arg)</strong>
+ </dt>
+ <dd>
+ return the index (or key) of a value in a table using a comparison function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ A table
+ </li>
+ <li><span class="parameter">cmp</span>
+ <span class="types"><span class="type">func</span></span>
+ A comparison function
+ </li>
+ <li><span class="parameter">arg</span>
+ an optional second argument to the function
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ index of value, or nil if not found</li>
+ <li>
+ value returned by comparison function</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "search"></a>
+ <strong>search (t, value[, exclude])</strong>
+ </dt>
+ <dd>
+ find a value in a table by recursive search.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ the table
+ </li>
+ <li><span class="parameter">value</span>
+ the value
+ </li>
+ <li><span class="parameter">exclude</span>
+ <span class="types"><span class="type">array</span></span>
+ any tables to avoid searching
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a fieldspec, e.g. &lsquo;a.b&rsquo; or &lsquo;math.sin&rsquo;
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">search(_G,<span class="global">math</span>.sin,{<span class="global">package</span>.path}) == <span class="string">'math.sin'</span></pre>
+ </ul>
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="MappingAndFiltering"></a>MappingAndFiltering</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "map"></a>
+ <strong>map (fun, t, ...)</strong>
+ </dt>
+ <dd>
+ apply a function to all values of a table.
+ This returns a table of the results.
+ Any extra arguments are passed to the function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ A function that takes at least one argument
+ </li>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ A table
+ </li>
+ <li><span class="parameter">...</span>
+ optional arguments
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">map(<span class="keyword">function</span>(v) <span class="keyword">return</span> v*v <span class="keyword">end</span>, {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,fred=<span class="number">2</span>}) is {<span class="number">100</span>,<span class="number">400</span>,<span class="number">900</span>,fred=<span class="number">4</span>}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "imap"></a>
+ <strong>imap (fun, t, ...)</strong>
+ </dt>
+ <dd>
+ apply a function to all values of a list.
+ This returns a table of the results.
+ Any extra arguments are passed to the function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ A function that takes at least one argument
+ </li>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a table (applies to array part)
+ </li>
+ <li><span class="parameter">...</span>
+ optional arguments
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list-like table
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">imap(<span class="keyword">function</span>(v) <span class="keyword">return</span> v*v <span class="keyword">end</span>, {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,fred=<span class="number">2</span>}) is {<span class="number">100</span>,<span class="number">400</span>,<span class="number">900</span>}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "map_named_method"></a>
+ <strong>map_named_method (name, t, ...)</strong>
+ </dt>
+ <dd>
+ apply a named method to values from a table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">name</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the method name
+ </li>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">...</span>
+ any extra arguments to the method
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "map2"></a>
+ <strong>map2 (fun, t1, t2, ...)</strong>
+ </dt>
+ <dd>
+ apply a function to values from two tables.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least two arguments
+ </li>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">...</span>
+ extra arguments
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">map2(<span class="string">'+'</span>,{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,m=<span class="number">4</span>},{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,m=<span class="number">40</span>}) is {<span class="number">11</span>,<span class="number">22</span>,<span class="number">23</span>,m=<span class="number">44</span>}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "imap2"></a>
+ <strong>imap2 (fun, t1, t2, ...)</strong>
+ </dt>
+ <dd>
+ apply a function to values from two arrays.
+ The result will be the length of the shortest array.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function of at least two arguments
+ </li>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">...</span>
+ extra arguments
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">imap2(<span class="string">'+'</span>,{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,m=<span class="number">4</span>},{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,m=<span class="number">40</span>}) is {<span class="number">11</span>,<span class="number">22</span>,<span class="number">23</span>}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "mapn"></a>
+ <strong>mapn (fun, ..., fun)</strong>
+ </dt>
+ <dd>
+ Apply a function to a number of tables.
+ A more general version of map
+ The result is a table containing the result of applying that function to the
+ ith value of each table. Length of output list is the minimum length of all the lists
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ A function that takes as many arguments as there are tables
+ </li>
+ <li><span class="parameter">...</span>
+ <span class="types"><span class="type">tab</span></span>
+ n tables
+ </li>
+ <li><span class="parameter">fun</span>
+ A function that takes as many arguments as there are tables
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">mapn(<span class="keyword">function</span>(x,y,z) <span class="keyword">return</span> x+y+z <span class="keyword">end</span>, {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>},{<span class="number">100</span>,<span class="number">200</span>,<span class="number">300</span>}) is {<span class="number">111</span>,<span class="number">222</span>,<span class="number">333</span>}</pre></li>
+ <li><pre class="example">mapn(<span class="global">math</span>.max, {<span class="number">1</span>,<span class="number">20</span>,<span class="number">300</span>},{<span class="number">10</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">100</span>,<span class="number">200</span>,<span class="number">100</span>}) is {<span class="number">100</span>,<span class="number">200</span>,<span class="number">300</span>}</pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "pairmap"></a>
+ <strong>pairmap (fun, t, ...)</strong>
+ </dt>
+ <dd>
+ call the function with the key and value pairs from a table.
+ The function can return a value and a key (note the order!). If both
+ are not nil, then this pair is inserted into the result: if the key already exists, we convert the value for that
+ key into a table and append into it. If only value is not nil, then it is appended to the result.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ A function which will be passed each key and value as arguments, plus any extra arguments to pairmap.
+ </li>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ A table
+ </li>
+ <li><span class="parameter">...</span>
+ optional arguments
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">pairmap(<span class="keyword">function</span>(k,v) <span class="keyword">return</span> v <span class="keyword">end</span>,{fred=<span class="number">10</span>,bonzo=<span class="number">20</span>}) is {<span class="number">10</span>,<span class="number">20</span>} _or_ {<span class="number">20</span>,<span class="number">10</span>}</pre></li>
+ <li><pre class="example">pairmap(<span class="keyword">function</span>(k,v) <span class="keyword">return</span> {k,v},k <span class="keyword">end</span>,{one=<span class="number">1</span>,two=<span class="number">2</span>}) is {one={<span class="string">'one'</span>,<span class="number">1</span>},two={<span class="string">'two'</span>,<span class="number">2</span>}}</pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "filter"></a>
+ <strong>filter (t, pred, arg)</strong>
+ </dt>
+ <dd>
+ filter an array&rsquo;s values using a predicate function
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">pred</span>
+ <span class="types"><span class="type">func</span></span>
+ a boolean function
+ </li>
+ <li><span class="parameter">arg</span>
+ optional argument to be passed as second argument of the predicate
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Iterating"></a>Iterating</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "foreach"></a>
+ <strong>foreach (t, fun, ...)</strong>
+ </dt>
+ <dd>
+ apply a function to all elements of a table.
+ The arguments to the function will be the value,
+ the key and <em>finally</em> any extra arguments passed to this function.
+ Note that the Lua 5.0 function table.foreach passed the <em>key</em> first.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function with at least one argument
+ </li>
+ <li><span class="parameter">...</span>
+ extra arguments
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "foreachi"></a>
+ <strong>foreachi (t, fun, ...)</strong>
+ </dt>
+ <dd>
+ apply a function to all elements of a list-like table in order.
+ The arguments to the function will be the value,
+ the index and <em>finally</em> any extra arguments passed to this function
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a table
+ </li>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a function with at least one argument
+ </li>
+ <li><span class="parameter">...</span>
+ optional arguments
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "sort"></a>
+ <strong>sort (t, f)</strong>
+ </dt>
+ <dd>
+ return an iterator to a table sorted by its keys
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ the table
+ </li>
+ <li><span class="parameter">f</span>
+ <span class="types"><span class="type">func</span></span>
+ an optional comparison function (f(x,y) is true if x &lt; y)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an iterator to traverse elements sorted by the keys
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">for</span> k,v <span class="keyword">in</span> tablex.sort(t) <span class="keyword">do</span> <span class="global">print</span>(k,v) <span class="keyword">end</span></pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "sortv"></a>
+ <strong>sortv (t, f)</strong>
+ </dt>
+ <dd>
+ return an iterator to a table sorted by its values
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ the table
+ </li>
+ <li><span class="parameter">f</span>
+ <span class="types"><span class="type">func</span></span>
+ an optional comparison function (f(x,y) is true if x &lt; y)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an iterator to traverse elements sorted by the values
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">for</span> k,v <span class="keyword">in</span> tablex.sortv(t) <span class="keyword">do</span> <span class="global">print</span>(k,v) <span class="keyword">end</span></pre>
+ </ul>
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Extraction"></a>Extraction</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "keys"></a>
+ <strong>keys (t)</strong>
+ </dt>
+ <dd>
+ return all the keys of a table in arbitrary order.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ A table
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "values"></a>
+ <strong>values (t)</strong>
+ </dt>
+ <dd>
+ return all the values of the table in arbitrary order
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">tab</span></span>
+ A table
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "sub"></a>
+ <strong>sub (t, first, last)</strong>
+ </dt>
+ <dd>
+ Extract a range from a table, like &lsquo;string.sub&rsquo;.
+ If first or last are negative then they are relative to the end of the list
+ eg. sub(t,-2) gives last 2 entries in a list, and
+ sub(t,-4,-2) gives from -4th to -2nd
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ <span class="types"><span class="type">array</span></span>
+ a list-like table
+ </li>
+ <li><span class="parameter">first</span>
+ <span class="types"><span class="type">int</span></span>
+ An index
+ </li>
+ <li><span class="parameter">last</span>
+ <span class="types"><span class="type">int</span></span>
+ An index
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a new List
+ </ol>
+
+
+
+
+</dd>
+</dl>
+ <h2 class="section-header "><a name="Merging"></a>Merging</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "merge"></a>
+ <strong>merge (t1, t2, dup)</strong>
+ </dt>
+ <dd>
+ combine two tables, either as union or intersection. Corresponds to
+ set operations for sets () but more general. Not particularly
+ useful for list-like tables.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t1</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">t2</span>
+ <span class="types"><span class="type">tab</span></span>
+ a table
+ </li>
+ <li><span class="parameter">dup</span>
+ <span class="types"><span class="type">bool</span></span>
+ true for a union, false for an intersection.
+ </li>
+ </ul>
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.tablex.html#index_map">tablex.index_map</a>
+ </ul>
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">merge({alice=<span class="number">23</span>,fred=<span class="number">34</span>},{bob=<span class="number">25</span>,fred=<span class="number">34</span>}) is {fred=<span class="number">34</span>}</pre></li>
+ <li><pre class="example">merge({alice=<span class="number">23</span>,fred=<span class="number">34</span>},{bob=<span class="number">25</span>,fred=<span class="number">34</span>},<span class="keyword">true</span>) is {bob=<span class="number">25</span>,fred=<span class="number">34</span>,alice=<span class="number">23</span>}</pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "difference"></a>
+ <strong>difference (s1, s2, symm)</strong>
+ </dt>
+ <dd>
+ a new table which is the difference of two tables.
+ With sets (where the values are all true) this is set difference and
+ symmetric difference depending on the third parameter.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s1</span>
+ <span class="types"><span class="type">tab</span></span>
+ a map-like table or set
+ </li>
+ <li><span class="parameter">s2</span>
+ <span class="types"><span class="type">tab</span></span>
+ a map-like table or set
+ </li>
+ <li><span class="parameter">symm</span>
+ <span class="types"><span class="type">bool</span></span>
+ symmetric difference (default false)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a map-like table or set
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "zip"></a>
+ <strong>zip (...)</strong>
+ </dt>
+ <dd>
+ return a table where each element is a table of the ith values of an arbitrary
+ number of tables. It is equivalent to a matrix transpose.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">...</span>
+ <span class="types"><span class="type">array</span></span>
+ arrays to be zipped
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">zip({<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>},{<span class="number">100</span>,<span class="number">200</span>,<span class="number">300</span>}) is {{<span class="number">10</span>,<span class="number">100</span>},{<span class="number">20</span>,<span class="number">200</span>},{<span class="number">30</span>,<span class="number">300</span>}}</pre>
+ </ul>
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.template.html b/docs/libraries/pl.template.html
new file mode 100644
index 0000000..0dcb1da
--- /dev/null
+++ b/docs/libraries/pl.template.html
@@ -0,0 +1,334 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><strong>pl.template</strong></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.template</code></h1>
+<p>A template preprocessor.</p>
+<p> Originally by <a href="http://lua-users.org/wiki/SlightlyLessSimpleLuaPreprocessor">Ricki Lake</a></p>
+
+<p> There are two rules:</p>
+
+<ul>
+<li>lines starting with # are Lua</li>
+<li>otherwise, <code>$(expr)</code> is the result of evaluating <code>expr</code></li>
+</ul>
+
+
+<p> Example:</p>
+
+<pre>
+# <span class="keyword">for</span> i = <span class="number">1</span>,<span class="number">3</span> <span class="keyword">do</span>
+ $(i) Hello, Word!
+# <span class="keyword">end</span>
+===&gt;
+<span class="number">1</span> Hello, Word!
+<span class="number">2</span> Hello, Word!
+<span class="number">3</span> Hello, Word!
+</pre>
+
+
+<p> Other escape characters can be used, when the defaults conflict
+ with the output language.</p>
+
+<pre>
+&gt; <span class="keyword">for</span> _,n <span class="keyword">in</span> <span class="global">pairs</span>{<span class="string">'one'</span>,<span class="string">'two'</span>,<span class="string">'three'</span>} <span class="keyword">do</span>
+static int l_${n} (luaState *state);
+&gt; <span class="keyword">end</span>
+</pre>
+
+
+<p> See <a href="../manual/03-strings.md.html#Another_Style_of_Template">the Guide</a>.</p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#substitute">substitute (str[, env])</a></td>
+ <td class="summary">expand the template using the specified environment.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#ct:render">ct:render ([env[, parent[, db]]])</a></td>
+ <td class="summary">executes the previously compiled template and renders it.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#compile">compile (str[, opts])</a></td>
+ <td class="summary">compiles the template.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "substitute"></a>
+ <strong>substitute (str[, env])</strong>
+ </dt>
+ <dd>
+ <p>expand the template using the specified environment.
+ This function will compile and render the template. For more performant
+ recurring usage use the two step approach by using <a href="../libraries/pl.template.html#compile">compile</a> and <a href="../libraries/pl.template.html#ct:render">ct:render</a>.
+ There are six special fields in the environment table <code>env</code></p>
+
+<ul>
+<li> <code>_parent</code>: continue looking up in this table (e.g. <code>_parent=_G</code>).</li>
+<li> <code>_brackets</code>: bracket pair that wraps inline Lua expressions, default is &lsquo;()&rsquo;.</li>
+<li> <code>_escape</code>: character marking Lua lines, default is &lsquo;#&rsquo;</li>
+<li> <code>_inline_escape</code>: character marking inline Lua expression, default is &lsquo;$&rsquo;.</li>
+<li> <code>_chunk_name</code>: chunk name for loaded templates, used if there
+ is an error in Lua code. Default is &lsquo;TMP&rsquo;.</li>
+<li> <code>_debug</code>: if truthy, the generated code will be printed upon a render error</li>
+</ul>
+
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">str</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the template string
+ </li>
+ <li><span class="parameter">env</span>
+ <span class="types"><span class="type">tab</span></span>
+ the environment
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <code>rendered template + nil + source_code</code>, or <code>nil + error + source_code</code>. The last
+ return value (<code>source_code</code>) is only returned if the debug option is used.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "ct:render"></a>
+ <strong>ct:render ([env[, parent[, db]]])</strong>
+ </dt>
+ <dd>
+ executes the previously compiled template and renders it.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">env</span>
+ <span class="types"><span class="type">tab</span></span>
+ the environment.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">parent</span>
+ <span class="types"><span class="type">tab</span></span>
+ continue looking up in this table (e.g. <code>parent=_G</code>).
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">db</span>
+ <span class="types"><span class="type">bool</span></span>
+ if thruthy, it will print the code upon a render error
+ (provided the template was compiled with the debug option).
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ <code>rendered template + nil + source_code</code>, or <code>nil + error + source_code</code>. The last return value
+ (<code>source_code</code>) is only returned if the template was compiled with the debug option.
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">local</span> ct, err = template.compile(my_template)
+<span class="keyword">local</span> rendered , err = ct:render(my_env, parent)</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "compile"></a>
+ <strong>compile (str[, opts])</strong>
+ </dt>
+ <dd>
+ <p>compiles the template.
+ Returns an object that can repeatedly be rendered without parsing/compiling
+ the template again.
+ The options passed in the <code>opts</code> table support the following options:</p>
+
+<ul>
+<li> <code>chunk_name</code>: chunk name for loaded templates, used if there
+ is an error in Lua code. Default is &lsquo;TMP&rsquo;.</li>
+<li> <code>escape</code>: character marking Lua lines, default is &lsquo;#&rsquo;</li>
+<li> <code>inline_escape</code>: character marking inline Lua expression, default is &lsquo;$&rsquo;.</li>
+<li> <code>inline_brackets</code>: bracket pair that wraps inline Lua expressions, default is &lsquo;()&rsquo;.</li>
+<li> <code>newline</code>: string to replace newline characters, default is <code>nil</code> (not replacing newlines).</li>
+<li> <a href="https://www.lua.org/manual/5.1/manual.html#5.9">debug</a>: if truthy, the generated source code will be retained within the compiled template object, default is <code>nil</code>.</li>
+</ul>
+
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">str</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the template string
+ </li>
+ <li><span class="parameter">opts</span>
+ <span class="types"><span class="type">tab</span></span>
+ the compilation options to use
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ template object, or <code>nil + error + source_code</code>
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">local</span> ct, err = template.compile(my_template)
+<span class="keyword">local</span> rendered , err = ct:render(my_env, parent)</pre>
+ </ul>
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.test.html b/docs/libraries/pl.test.html
new file mode 100644
index 0000000..3719fd8
--- /dev/null
+++ b/docs/libraries/pl.test.html
@@ -0,0 +1,432 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><strong>pl.test</strong></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.test</code></h1>
+<p>Useful test utilities.</p>
+<p>
+
+<pre>
+test.asserteq({<span class="number">1</span>,<span class="number">2</span>},{<span class="number">1</span>,<span class="number">2</span>}) <span class="comment">-- can compare tables
+</span>test.asserteq(<span class="number">1.2</span>,<span class="number">1.19</span>,<span class="number">0.02</span>) <span class="comment">-- compare FP numbers within precision
+</span>T = test.tuple <span class="comment">-- used for comparing multiple results
+</span>test.asserteq(T(<span class="global">string</span>.find(<span class="string">" me"</span>,<span class="string">"me"</span>)),T(<span class="number">2</span>,<span class="number">3</span>))
+</pre>
+
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.tablex.html#">pl.tablex</a>, <a href="../libraries/pl.pretty.html#">pl.pretty</a>, <a href="../libraries/pl.path.html#">pl.path</a>, <a href="https://www.lua.org/manual/5.1/manual.html#5.9">debug</a></p></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#error_handler">error_handler (file, line, got_text, needed_text, msg)</a></td>
+ <td class="summary">error handling for test results.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#complain">complain (x, y, msg, where)</a></td>
+ <td class="summary">general test complain message.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#asserteq">asserteq (x, y, eps, where)</a></td>
+ <td class="summary">like assert, except takes two arguments that must be equal and can be tables.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#assertmatch">assertmatch (s1, s2, where)</a></td>
+ <td class="summary">assert that the first string matches the second.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#assertraise">assertraise (fn, e, where)</a></td>
+ <td class="summary">assert that the function raises a particular error.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#asserteq2">asserteq2 (x1, x2, y1, y2, where)</a></td>
+ <td class="summary">a version of asserteq that takes two pairs of values.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#tuple">tuple (...)</a></td>
+ <td class="summary">encode an arbitrary argument list as a tuple.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#timer">timer (msg, n, fun, ...)</a></td>
+ <td class="summary">Time a function.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "error_handler"></a>
+ <strong>error_handler (file, line, got_text, needed_text, msg)</strong>
+ </dt>
+ <dd>
+ error handling for test results.
+ By default, this writes to stderr and exits the program.
+ Re-define this function to raise an error and/or redirect output
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">file</span>
+
+ </li>
+ <li><span class="parameter">line</span>
+
+ </li>
+ <li><span class="parameter">got_text</span>
+
+ </li>
+ <li><span class="parameter">needed_text</span>
+
+ </li>
+ <li><span class="parameter">msg</span>
+
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "complain"></a>
+ <strong>complain (x, y, msg, where)</strong>
+ </dt>
+ <dd>
+ general test complain message.
+ Useful for composing new test functions (see tests/tablex.lua for an example)
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x</span>
+ a value
+ </li>
+ <li><span class="parameter">y</span>
+ value to compare first value against
+ </li>
+ <li><span class="parameter">msg</span>
+ message
+ </li>
+ <li><span class="parameter">where</span>
+ extra level offset for errors
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "asserteq"></a>
+ <strong>asserteq (x, y, eps, where)</strong>
+ </dt>
+ <dd>
+ like assert, except takes two arguments that must be equal and can be tables.
+ If they are plain tables, it will use tablex.deepcompare.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x</span>
+ any value
+ </li>
+ <li><span class="parameter">y</span>
+ a value equal to x
+ </li>
+ <li><span class="parameter">eps</span>
+ an optional tolerance for numerical comparisons
+ </li>
+ <li><span class="parameter">where</span>
+ extra level offset
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "assertmatch"></a>
+ <strong>assertmatch (s1, s2, where)</strong>
+ </dt>
+ <dd>
+ assert that the first string matches the second.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s1</span>
+ a string
+ </li>
+ <li><span class="parameter">s2</span>
+ a string
+ </li>
+ <li><span class="parameter">where</span>
+ extra level offset
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "assertraise"></a>
+ <strong>assertraise (fn, e, where)</strong>
+ </dt>
+ <dd>
+ assert that the function raises a particular error.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fn</span>
+ a function or a table of the form {function,arg1,&hellip;}
+ </li>
+ <li><span class="parameter">e</span>
+ a string to match the error against
+ </li>
+ <li><span class="parameter">where</span>
+ extra level offset
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "asserteq2"></a>
+ <strong>asserteq2 (x1, x2, y1, y2, where)</strong>
+ </dt>
+ <dd>
+ a version of asserteq that takes two pairs of values.
+ <code>x1==y1 and x2==y2</code> must be true. Useful for functions that naturally
+ return two values.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x1</span>
+ any value
+ </li>
+ <li><span class="parameter">x2</span>
+ any value
+ </li>
+ <li><span class="parameter">y1</span>
+ any value
+ </li>
+ <li><span class="parameter">y2</span>
+ any value
+ </li>
+ <li><span class="parameter">where</span>
+ extra level offset
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "tuple"></a>
+ <strong>tuple (...)</strong>
+ </dt>
+ <dd>
+ encode an arbitrary argument list as a tuple.
+ This can be used to compare to other argument lists, which is
+ very useful for testing functions which return a number of values.
+ Unlike regular array-like tables (&lsquo;sequences&rsquo;) they may contain nils.
+ Tuples understand equality and know how to print themselves out.
+ The # operator is defined to be the size, irrespecive of any nils,
+ and there is an <a href="https://www.lua.org/manual/5.1/manual.html#pdf-unpack">unpack</a> method.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">...</span>
+
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">asserteq(tuple( (<span class="string">'ab'</span>):find <span class="string">'a'</span>), tuple(<span class="number">1</span>,<span class="number">1</span>))</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "timer"></a>
+ <strong>timer (msg, n, fun, ...)</strong>
+ </dt>
+ <dd>
+ Time a function. Call the function a given number of times, and report the number of seconds taken,
+ together with a message. Any extra arguments will be passed to the function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">msg</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ a descriptive message
+ </li>
+ <li><span class="parameter">n</span>
+ <span class="types"><span class="type">int</span></span>
+ number of times to call the function
+ </li>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ the function
+ </li>
+ <li><span class="parameter">...</span>
+ optional arguments to fun
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.text.html b/docs/libraries/pl.text.html
new file mode 100644
index 0000000..360f7a9
--- /dev/null
+++ b/docs/libraries/pl.text.html
@@ -0,0 +1,378 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><strong>pl.text</strong></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.text</code></h1>
+<p>Text processing utilities.</p>
+<p> This provides a Template class (modeled after the same from the Python
+ libraries, see string.Template). It also provides similar functions to those
+ found in the textwrap module.</p>
+
+<p> See <a href="../manual/03-strings.md.html#String_Templates">the Guide</a>.</p>
+
+<p> Calling <code>text.format_operator()</code> overloads the % operator for strings to give Python/Ruby style formated output.
+ This is extended to also do template-like substitution for map-like data.</p>
+
+<pre>
+&gt; <span class="global">require</span> <span class="string">'pl.text'</span>.format_operator()
+&gt; = <span class="string">'%s = %5.3f'</span> % {<span class="string">'PI'</span>,<span class="global">math</span>.pi}
+PI = <span class="number">3.142</span>
+&gt; = <span class="string">'$name = $value'</span> % {name=<span class="string">'dog'</span>,value=<span class="string">'Pluto'</span>}
+dog = Pluto
+</pre>
+
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a>, <a href="../libraries/pl.types.html#">pl.types</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#indent">indent (s, n, ch)</a></td>
+ <td class="summary">indent a multiline string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#dedent">dedent (s)</a></td>
+ <td class="summary">dedent a multiline string by removing any initial indent.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#wrap">wrap (s, width)</a></td>
+ <td class="summary">format a paragraph into lines so that they fit into a line width.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#fill">fill (s, width)</a></td>
+ <td class="summary">format a paragraph so that it fits into a line width.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Template:substitute">Template:substitute (tbl)</a></td>
+ <td class="summary">substitute values into a template, throwing an error.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Template:safe_substitute">Template:safe_substitute (tbl)</a></td>
+ <td class="summary">substitute values into a template.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Template:indent_substitute">Template:indent_substitute (tbl)</a></td>
+ <td class="summary">substitute values into a template, preserving indentation.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "indent"></a>
+ <strong>indent (s, n, ch)</strong>
+ </dt>
+ <dd>
+ indent a multiline string.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ the string
+ </li>
+ <li><span class="parameter">n</span>
+ the size of the indent
+ </li>
+ <li><span class="parameter">ch</span>
+ the character to use when indenting (default &lsquo; &rsquo;)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ indented string
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "dedent"></a>
+ <strong>dedent (s)</strong>
+ </dt>
+ <dd>
+ dedent a multiline string by removing any initial indent.
+ useful when working with [[..]] strings.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ the string
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string with initial indent zero.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "wrap"></a>
+ <strong>wrap (s, width)</strong>
+ </dt>
+ <dd>
+ format a paragraph into lines so that they fit into a line width.
+ It will not break long words, so lines can be over the length
+ to that extent.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ the string
+ </li>
+ <li><span class="parameter">width</span>
+ the margin width, default 70
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list of lines
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "fill"></a>
+ <strong>fill (s, width)</strong>
+ </dt>
+ <dd>
+ format a paragraph so that it fits into a line width.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ the string
+ </li>
+ <li><span class="parameter">width</span>
+ the margin width, default 70
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.text.html#wrap">wrap</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "Template:substitute"></a>
+ <strong>Template:substitute (tbl)</strong>
+ </dt>
+ <dd>
+ substitute values into a template, throwing an error.
+ This will throw an error if no name is found.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tbl</span>
+ a table of name-value pairs.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Template:safe_substitute"></a>
+ <strong>Template:safe_substitute (tbl)</strong>
+ </dt>
+ <dd>
+ substitute values into a template.
+ This version just passes unknown names through.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tbl</span>
+ a table of name-value pairs.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Template:indent_substitute"></a>
+ <strong>Template:indent_substitute (tbl)</strong>
+ </dt>
+ <dd>
+ substitute values into a template, preserving indentation. <br>
+ If the value is a multiline string <em>or</em> a template, it will insert
+ the lines at the correct indentation. <br>
+ Furthermore, if a template, then that template will be subsituted
+ using the same table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tbl</span>
+ a table of name-value pairs.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.types.html b/docs/libraries/pl.types.html
new file mode 100644
index 0000000..e4d0b9f
--- /dev/null
+++ b/docs/libraries/pl.types.html
@@ -0,0 +1,412 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><strong>pl.types</strong></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.types</code></h1>
+<p>Dealing with Detailed Type Information</p>
+<p></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#is_callable">is_callable (obj)</a></td>
+ <td class="summary">is the object either a function or a callable object?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_type">is_type (obj, tp)</a></td>
+ <td class="summary">is the object of the specified type?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#type">type (obj)</a></td>
+ <td class="summary">a string representation of a type.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_integer">is_integer (x)</a></td>
+ <td class="summary">is this number an integer?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_empty">is_empty (o, ignore_spaces)</a></td>
+ <td class="summary">Check if the object is &ldquo;empty&rdquo;.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_indexable">is_indexable (val)</a></td>
+ <td class="summary">is an object &lsquo;array-like&rsquo;?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_iterable">is_iterable (val)</a></td>
+ <td class="summary">can an object be iterated over with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a>?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_writeable">is_writeable (val)</a></td>
+ <td class="summary">can an object accept new key/pair values?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#to_bool">to_bool (o[, true_strs[, check_objs]])</a></td>
+ <td class="summary">Convert to a boolean value.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "is_callable"></a>
+ <strong>is_callable (obj)</strong>
+ </dt>
+ <dd>
+ is the object either a function or a callable object?.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">obj</span>
+ Object to check.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "is_type"></a>
+ <strong>is_type (obj, tp)</strong>
+ </dt>
+ <dd>
+ is the object of the specified type?.
+ If the type is a string, then use type, otherwise compare with metatable
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">obj</span>
+ An object to check
+ </li>
+ <li><span class="parameter">tp</span>
+ String of what type it should be
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "type"></a>
+ <strong>type (obj)</strong>
+ </dt>
+ <dd>
+ a string representation of a type.
+ For tables with metatables, we assume that the metatable has a <code>_name</code>
+ field. Knows about Lua file objects.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">obj</span>
+ an object
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string like &lsquo;number&rsquo;, &lsquo;table&rsquo; or &lsquo;List&rsquo;
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "is_integer"></a>
+ <strong>is_integer (x)</strong>
+ </dt>
+ <dd>
+ is this number an integer?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">x</span>
+ a number
+ </li>
+ </ul>
+
+
+ <h3>Raises:</h3>
+ error if x is not a number
+
+
+
+</dd>
+ <dt>
+ <a name = "is_empty"></a>
+ <strong>is_empty (o, ignore_spaces)</strong>
+ </dt>
+ <dd>
+ Check if the object is &ldquo;empty&rdquo;.
+ An object is considered empty if it is nil, a table with out any items (key,
+ value pairs or indexes), or a string with no content (&ldquo;&rdquo;).
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">o</span>
+ The object to check if it is empty.
+ </li>
+ <li><span class="parameter">ignore_spaces</span>
+ If the object is a string and this is true the string is
+ considered empty is it only contains spaces.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true if the object is empty, otherwise false.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "is_indexable"></a>
+ <strong>is_indexable (val)</strong>
+ </dt>
+ <dd>
+ is an object &lsquo;array-like&rsquo;?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">val</span>
+ any value.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "is_iterable"></a>
+ <strong>is_iterable (val)</strong>
+ </dt>
+ <dd>
+ can an object be iterated over with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a>?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">val</span>
+ any value.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "is_writeable"></a>
+ <strong>is_writeable (val)</strong>
+ </dt>
+ <dd>
+ can an object accept new key/pair values?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">val</span>
+ any value.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "to_bool"></a>
+ <strong>to_bool (o[, true_strs[, check_objs]])</strong>
+ </dt>
+ <dd>
+ <p>Convert to a boolean value.
+ True values are:</p>
+
+<ul>
+<li>boolean: true.</li>
+<li>string: &lsquo;yes&rsquo;, &lsquo;y&rsquo;, &lsquo;true&rsquo;, &rsquo;t', &lsquo;1&rsquo; or additional strings specified by <code>true_strs</code>.</li>
+<li>number: Any non-zero value.</li>
+<li>table: Is not empty and <code>check_objs</code> is true.</li>
+<li>object: Is not <code>nil</code> and <code>check_objs</code> is true.</li>
+</ul>
+
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">o</span>
+ The object to evaluate.
+ </li>
+ <li><span class="parameter">true_strs</span>
+ optional Additional strings that when matched should evaluate to true. Comparison is case insensitive.
+ This should be a List of strings. E.g. &ldquo;ja&rdquo; to support German.
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">check_objs</span>
+ True if objects should be evaluated. Default is to evaluate objects as true if not nil
+ or if it is a table and it is not empty.
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ true if the input evaluates to true, otherwise false.
+ </ol>
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.url.html b/docs/libraries/pl.url.html
new file mode 100644
index 0000000..e95df60
--- /dev/null
+++ b/docs/libraries/pl.url.html
@@ -0,0 +1,201 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><strong>pl.url</strong></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.url</code></h1>
+<p>Python-style URL quoting library.</p>
+<p></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#quote">quote (s, quote_plus)</a></td>
+ <td class="summary">Quote the url, replacing special characters using the &lsquo;%xx&rsquo; escape.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#unquote">unquote (s)</a></td>
+ <td class="summary">Unquote the url, replacing &lsquo;%xx&rsquo; escapes and plus signs.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "quote"></a>
+ <strong>quote (s, quote_plus)</strong>
+ </dt>
+ <dd>
+ Quote the url, replacing special characters using the &lsquo;%xx&rsquo; escape.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ <li><span class="parameter">quote_plus</span>
+ <span class="types"><span class="type">bool</span></span>
+ Also escape slashes and replace spaces by plus signs.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "unquote"></a>
+ <strong>unquote (s)</strong>
+ </dt>
+ <dd>
+ Unquote the url, replacing &lsquo;%xx&rsquo; escapes and plus signs.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.utils.html b/docs/libraries/pl.utils.html
new file mode 100644
index 0000000..28d0ed1
--- /dev/null
+++ b/docs/libraries/pl.utils.html
@@ -0,0 +1,1179 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><strong>pl.utils</strong></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.utils</code></h1>
+<p>Generally useful routines.</p>
+<p> See <a href="../manual/01-introduction.md.html#Generally_useful_functions_">the Guide</a>.</p>
+
+<p> Dependencies: <a href="../libraries/pl.compat.html#">pl.compat</a></p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#pack">pack (...)</a></td>
+ <td class="summary">pack an argument list into a table.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#unpack">unpack (t[, i[, t]])</a></td>
+ <td class="summary">unpack a table and return its contents.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#quit">quit (code, ...)</a></td>
+ <td class="summary">end this program gracefully.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#printf">printf (fmt, ...)</a></td>
+ <td class="summary">print an arbitrary number of arguments using a format.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#fprintf">fprintf (f, fmt, ...)</a></td>
+ <td class="summary">write an arbitrary number of arguments to a file using a format.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#import">import (t, T)</a></td>
+ <td class="summary">take a table and &lsquo;inject&rsquo; it into the local namespace.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#escape">escape (s)</a></td>
+ <td class="summary">escape any &lsquo;magic&rsquo; characters in a string</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#choose">choose (cond, value1, value2)</a></td>
+ <td class="summary">return either of two values, depending on a condition.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#readfile">readfile (filename, is_bin)</a></td>
+ <td class="summary">return the contents of a file as a string</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#writefile">writefile (filename, str, is_bin)</a></td>
+ <td class="summary">write a string to a file</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#readlines">readlines (filename)</a></td>
+ <td class="summary">return the contents of a file as a list of lines</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#split">split (s, re, plain, n)</a></td>
+ <td class="summary">split a string into a list of strings separated by a delimiter.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#splitv">splitv (s, re)</a></td>
+ <td class="summary">split a string into a number of values.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#array_tostring">array_tostring (t, temp, tostr)</a></td>
+ <td class="summary">convert an array of values to strings.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#quote_arg">quote_arg (argument)</a></td>
+ <td class="summary">Quote an argument of a command.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#executeex">executeex (cmd, bin)</a></td>
+ <td class="summary">execute a shell command and return the output.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#memoize">memoize (func)</a></td>
+ <td class="summary">&lsquo;memoize&rsquo; a function (cache returned value for next call).</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#add_function_factory">add_function_factory (mt, fun)</a></td>
+ <td class="summary">associate a function factory with a type.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#string_lambda">string_lambda (lf)</a></td>
+ <td class="summary">an anonymous function as a string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#function_arg">function_arg (idx, f, msg)</a></td>
+ <td class="summary">process a function argument.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#bind1">bind1 (fn, p)</a></td>
+ <td class="summary">bind the first argument of the function to a value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#bind2">bind2 (fn, p)</a></td>
+ <td class="summary">bind the second argument of the function to a value.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#assert_arg">assert_arg (n, val, tp, verify, msg, lev)</a></td>
+ <td class="summary">assert that the given argument is in fact of the correct type.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#assert_string">assert_string (n, val)</a></td>
+ <td class="summary">assert the common case that the argument is a string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#on_error">on_error (mode)</a></td>
+ <td class="summary">control the error strategy used by Penlight.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#raise">raise (err)</a></td>
+ <td class="summary">used by Penlight functions to return errors.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_type">is_type (obj, tp)</a></td>
+ <td class="summary">is the object of the specified type?.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#load">load (code, name, mode, env)</a></td>
+ <td class="summary">load a code string or bytecode chunk.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#getfenv">getfenv (f)</a></td>
+ <td class="summary">Get environment of a function.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#setfenv">setfenv (f, env)</a></td>
+ <td class="summary">Set environment of a function</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#execute">execute (cmd)</a></td>
+ <td class="summary">execute a shell command.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "pack"></a>
+ <strong>pack (...)</strong>
+ </dt>
+ <dd>
+ pack an argument list into a table.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">...</span>
+ any arguments
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a table with field n set to the length
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "unpack"></a>
+ <strong>unpack (t[, i[, t]])</strong>
+ </dt>
+ <dd>
+ unpack a table and return its contents.
+ NOTE: this implementation differs from the Lua implementation in the way
+ that this one DOES honor the n field in the table t, such that it is &lsquo;nil-safe&rsquo;.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ index of the last element to unpack, defaults to <code>t.n</code> or #t
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">i</span>
+ index from which to start unpacking, defaults to 1
+ (<em>optional</em>)
+ </li>
+ <li><span class="parameter">t</span>
+ index of the last element to unpack, defaults to <code>t.n</code> or #t
+ (<em>optional</em>)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ multiple returns values from the table
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "quit"></a>
+ <strong>quit (code, ...)</strong>
+ </dt>
+ <dd>
+ end this program gracefully.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">code</span>
+ The exit code or a message to be printed
+ </li>
+ <li><span class="parameter">...</span>
+ extra arguments for message&rsquo;s format'
+ </li>
+ </ul>
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.utils.html#fprintf">utils.fprintf</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "printf"></a>
+ <strong>printf (fmt, ...)</strong>
+ </dt>
+ <dd>
+ print an arbitrary number of arguments using a format.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fmt</span>
+ The format (see string.format)
+ </li>
+ <li><span class="parameter">...</span>
+ Extra arguments for format
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "fprintf"></a>
+ <strong>fprintf (f, fmt, ...)</strong>
+ </dt>
+ <dd>
+ write an arbitrary number of arguments to a file using a format.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ File handle to write to.
+ </li>
+ <li><span class="parameter">fmt</span>
+ The format (see string.format).
+ </li>
+ <li><span class="parameter">...</span>
+ Extra arguments for format
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "import"></a>
+ <strong>import (t, T)</strong>
+ </dt>
+ <dd>
+ take a table and &lsquo;inject&rsquo; it into the local namespace.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ The Table
+ </li>
+ <li><span class="parameter">T</span>
+ An optional destination table (defaults to callers environment)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "escape"></a>
+ <strong>escape (s)</strong>
+ </dt>
+ <dd>
+ escape any &lsquo;magic&rsquo; characters in a string
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ The input string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "choose"></a>
+ <strong>choose (cond, value1, value2)</strong>
+ </dt>
+ <dd>
+ return either of two values, depending on a condition.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">cond</span>
+ A condition
+ </li>
+ <li><span class="parameter">value1</span>
+ Value returned if cond is true
+ </li>
+ <li><span class="parameter">value2</span>
+ Value returned if cond is false (can be optional)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "readfile"></a>
+ <strong>readfile (filename, is_bin)</strong>
+ </dt>
+ <dd>
+ return the contents of a file as a string
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">filename</span>
+ The file path
+ </li>
+ <li><span class="parameter">is_bin</span>
+ open in binary mode
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ file contents
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "writefile"></a>
+ <strong>writefile (filename, str, is_bin)</strong>
+ </dt>
+ <dd>
+ write a string to a file
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">filename</span>
+ The file path
+ </li>
+ <li><span class="parameter">str</span>
+ The string
+ </li>
+ <li><span class="parameter">is_bin</span>
+ open in binary mode
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ true or nil</li>
+ <li>
+ error message</li>
+ </ol>
+
+ <h3>Raises:</h3>
+ error if filename or str aren&rsquo;t strings
+
+
+
+</dd>
+ <dt>
+ <a name = "readlines"></a>
+ <strong>readlines (filename)</strong>
+ </dt>
+ <dd>
+ return the contents of a file as a list of lines
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">filename</span>
+ The file path
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ file contents as a table
+ </ol>
+
+ <h3>Raises:</h3>
+ errror if filename is not a string
+
+
+
+</dd>
+ <dt>
+ <a name = "split"></a>
+ <strong>split (s, re, plain, n)</strong>
+ </dt>
+ <dd>
+ split a string into a list of strings separated by a delimiter.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ The input string
+ </li>
+ <li><span class="parameter">re</span>
+ A Lua string pattern; defaults to &lsquo;%s+&rsquo;
+ </li>
+ <li><span class="parameter">plain</span>
+ don&rsquo;t use Lua patterns
+ </li>
+ <li><span class="parameter">n</span>
+ optional maximum number of splits
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list-like table
+ </ol>
+
+ <h3>Raises:</h3>
+ error if s is not a string
+
+
+
+</dd>
+ <dt>
+ <a name = "splitv"></a>
+ <strong>splitv (s, re)</strong>
+ </dt>
+ <dd>
+ split a string into a number of values.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ the string
+ </li>
+ <li><span class="parameter">re</span>
+ the delimiter, default space
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ n values
+ </ol>
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.utils.html#split">split</a>
+ </ul>
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example">first,<span class="global">next</span> = splitv(<span class="string">'jane:doe'</span>,<span class="string">':'</span>)</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "array_tostring"></a>
+ <strong>array_tostring (t, temp, tostr)</strong>
+ </dt>
+ <dd>
+ convert an array of values to strings.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a list-like table
+ </li>
+ <li><span class="parameter">temp</span>
+ buffer to use, otherwise allocate
+ </li>
+ <li><span class="parameter">tostr</span>
+ custom tostring function, called with (value,index).
+ Otherwise use <a href="https://www.lua.org/manual/5.1/manual.html#pdf-tostring">tostring</a>
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ the converted buffer
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "quote_arg"></a>
+ <strong>quote_arg (argument)</strong>
+ </dt>
+ <dd>
+ Quote an argument of a command.
+ Quotes a single argument of a command to be passed
+ to <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.execute">os.execute</a>, <a href="../libraries/pl.utils.html#execute">pl.utils.execute</a> or <a href="../libraries/pl.utils.html#executeex">pl.utils.executeex</a>.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">argument</span>
+ <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+ the argument.
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ quoted argument.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "executeex"></a>
+ <strong>executeex (cmd, bin)</strong>
+ </dt>
+ <dd>
+ execute a shell command and return the output.
+ This function redirects the output to tempfiles and returns the content of those files.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">cmd</span>
+ a shell command
+ </li>
+ <li><span class="parameter">bin</span>
+ boolean, if true, read output as binary file
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ true if successful</li>
+ <li>
+ actual return code</li>
+ <li>
+ stdout output (string)</li>
+ <li>
+ errout output (string)</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "memoize"></a>
+ <strong>memoize (func)</strong>
+ </dt>
+ <dd>
+ &lsquo;memoize&rsquo; a function (cache returned value for next call).
+ This is useful if you have a function which is relatively expensive,
+ but you don&rsquo;t know in advance what values will be required, so
+ building a table upfront is wasteful/impossible.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">func</span>
+ a function of at least one argument
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function with at least one argument, which is used as the key.
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "add_function_factory"></a>
+ <strong>add_function_factory (mt, fun)</strong>
+ </dt>
+ <dd>
+ associate a function factory with a type.
+ A function factory takes an object of the given type and
+ returns a function for evaluating it
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">mt</span>
+ <span class="types"><span class="type">tab</span></span>
+ metatable
+ </li>
+ <li><span class="parameter">fun</span>
+ <span class="types"><span class="type">func</span></span>
+ a callable that returns a function
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "string_lambda"></a>
+ <strong>string_lambda (lf)</strong>
+ </dt>
+ <dd>
+ an anonymous function as a string. This string is either of the form
+ &lsquo;|args| expression&rsquo; or is a function of one argument, &lsquo;_&rsquo;
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">lf</span>
+ function as a string
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function
+ </ol>
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">string_lambda <span class="string">'|x|x+1'</span> (<span class="number">2</span>) == <span class="number">3</span></pre></li>
+ <li><pre class="example">string_lambda <span class="string">'_+1'</span> (<span class="number">2</span>) == <span class="number">3</span></pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "function_arg"></a>
+ <strong>function_arg (idx, f, msg)</strong>
+ </dt>
+ <dd>
+ process a function argument.
+ This is used throughout Penlight and defines what is meant by a function:
+ Something that is callable, or an operator string as defined by <code>pl.operator</code>,
+ such as &lsquo;>&rsquo; or &lsquo;#&rsquo;. If a function factory has been registered for the type, it will
+ be called to get the function.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">idx</span>
+ argument index
+ </li>
+ <li><span class="parameter">f</span>
+ a function, operator string, or callable object
+ </li>
+ <li><span class="parameter">msg</span>
+ optional error message
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a callable
+ </ol>
+
+ <h3>Raises:</h3>
+ if idx is not a number or if f is not callable
+
+
+
+</dd>
+ <dt>
+ <a name = "bind1"></a>
+ <strong>bind1 (fn, p)</strong>
+ </dt>
+ <dd>
+ bind the first argument of the function to a value.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fn</span>
+ a function of at least two values (may be an operator string)
+ </li>
+ <li><span class="parameter">p</span>
+ a value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function such that f(x) is fn(p,x)
+ </ol>
+
+ <h3>Raises:</h3>
+ same as <a href="../libraries/pl.utils.html#function_arg">function_arg</a>
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.func.html#bind1">func.bind1</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "bind2"></a>
+ <strong>bind2 (fn, p)</strong>
+ </dt>
+ <dd>
+ bind the second argument of the function to a value.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">fn</span>
+ a function of at least two values (may be an operator string)
+ </li>
+ <li><span class="parameter">p</span>
+ a value
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a function such that f(x) is fn(x,p)
+ </ol>
+
+ <h3>Raises:</h3>
+ same as <a href="../libraries/pl.utils.html#function_arg">function_arg</a>
+
+
+
+</dd>
+ <dt>
+ <a name = "assert_arg"></a>
+ <strong>assert_arg (n, val, tp, verify, msg, lev)</strong>
+ </dt>
+ <dd>
+ assert that the given argument is in fact of the correct type.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">n</span>
+ argument index
+ </li>
+ <li><span class="parameter">val</span>
+ the value
+ </li>
+ <li><span class="parameter">tp</span>
+ the type
+ </li>
+ <li><span class="parameter">verify</span>
+ an optional verification function
+ </li>
+ <li><span class="parameter">msg</span>
+ an optional custom message
+ </li>
+ <li><span class="parameter">lev</span>
+ optional stack position for trace, default 2
+ </li>
+ </ul>
+
+
+ <h3>Raises:</h3>
+ if the argument n is not the correct type
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <li><pre class="example">assert_arg(<span class="number">1</span>,t,<span class="string">'table'</span>)</pre></li>
+ <li><pre class="example">assert_arg(n,val,<span class="string">'string'</span>,path.isdir,<span class="string">'not a directory'</span>)</pre></li>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "assert_string"></a>
+ <strong>assert_string (n, val)</strong>
+ </dt>
+ <dd>
+ assert the common case that the argument is a string.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">n</span>
+ argument index
+ </li>
+ <li><span class="parameter">val</span>
+ a value that must be a string
+ </li>
+ </ul>
+
+
+ <h3>Raises:</h3>
+ val must be a string
+
+
+
+</dd>
+ <dt>
+ <a name = "on_error"></a>
+ <strong>on_error (mode)</strong>
+ </dt>
+ <dd>
+ control the error strategy used by Penlight.
+ Controls how <code>utils.raise</code> works; the default is for it
+ to return nil and the error string, but if the mode is &lsquo;error&rsquo; then
+ it will throw an error. If mode is &lsquo;quit&rsquo; it will immediately terminate
+ the program.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">mode</span>
+ <ul>
+<li>either &lsquo;default&rsquo;, &lsquo;quit&rsquo; or &lsquo;error&rsquo;</li>
+</ul>
+
+ </li>
+ </ul>
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.utils.html#raise">utils.raise</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "raise"></a>
+ <strong>raise (err)</strong>
+ </dt>
+ <dd>
+ used by Penlight functions to return errors. Its global behaviour is controlled
+ by <code>utils.on_error</code>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">err</span>
+ the error string.
+ </li>
+ </ul>
+
+
+
+ <h3>See also:</h3>
+ <ul>
+ <a href="../libraries/pl.utils.html#on_error">utils.on_error</a>
+ </ul>
+
+
+</dd>
+ <dt>
+ <a name = "is_type"></a>
+ <strong>is_type (obj, tp)</strong>
+ </dt>
+ <dd>
+ is the object of the specified type?.
+ If the type is a string, then use type, otherwise compare with metatable
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">obj</span>
+ An object to check
+ </li>
+ <li><span class="parameter">tp</span>
+ String of what type it should be
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "load"></a>
+ <strong>load (code, name, mode, env)</strong>
+ </dt>
+ <dd>
+ load a code string or bytecode chunk.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">code</span>
+ Lua code as a string or bytecode
+ </li>
+ <li><span class="parameter">name</span>
+ for source errors
+ </li>
+ <li><span class="parameter">mode</span>
+ kind of chunk, &rsquo;t' for text, &lsquo;b&rsquo; for bytecode, &lsquo;bt&rsquo; for all (default)
+ </li>
+ <li><span class="parameter">env</span>
+ the environment for the new chunk (default nil)
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ compiled chunk</li>
+ <li>
+ error message (chunk is nil)</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "getfenv"></a>
+ <strong>getfenv (f)</strong>
+ </dt>
+ <dd>
+ Get environment of a function.
+ With Lua 5.2, may return nil for a function with no global references!
+ Based on code by <a href="http://lua-users.org/lists/lua-l/2010-06/msg00313.html">Sergey Rozhenko</a>
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function or a call stack reference
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "setfenv"></a>
+ <strong>setfenv (f, env)</strong>
+ </dt>
+ <dd>
+ Set environment of a function
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">f</span>
+ a function or a call stack reference
+ </li>
+ <li><span class="parameter">env</span>
+ a table that becomes the new environment of <code>f</code>
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "execute"></a>
+ <strong>execute (cmd)</strong>
+ </dt>
+ <dd>
+ execute a shell command.
+ This is a compatibility function that returns the same for Lua 5.1 and Lua 5.2
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">cmd</span>
+ a shell command
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ true if successful</li>
+ <li>
+ actual return code</li>
+ </ol>
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/libraries/pl.xml.html b/docs/libraries/pl.xml.html
new file mode 100644
index 0000000..f1ac5d9
--- /dev/null
+++ b/docs/libraries/pl.xml.html
@@ -0,0 +1,836 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Functions">Functions</a></li>
+</ul>
+
+
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><strong>pl.xml</strong></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Module <code>pl.xml</code></h1>
+<p>XML LOM Utilities.</p>
+<p> This implements some useful things on <a href="http://matthewwild.co.uk/projects/luaexpat/lom.html">LOM</a> documents, such as returned by <code>lxp.lom.parse</code>.
+ In particular, it can convert LOM back into XML text, with optional pretty-printing control.
+ It is s based on stanza.lua from <a href="http://hg.prosody.im/trunk/file/4621c92d2368/util/stanza.lua">Prosody</a></p>
+
+<pre>
+&gt; d = xml.parse <span class="string">"&lt;nodes&gt;&lt;node id='1'&gt;alice&lt;/node&gt;&lt;/nodes&gt;"</span>
+&gt; = d
+&lt;nodes&gt;&lt;node id=<span class="string">'1'</span>&gt;alice&lt;/node&gt;&lt;/nodes&gt;
+&gt; = xml.<span class="global">tostring</span>(d,<span class="string">''</span>,<span class="string">' '</span>)
+&lt;nodes&gt;
+ &lt;node id=<span class="string">'1'</span>&gt;alice&lt;/node&gt;
+&lt;/nodes&gt;
+</pre>
+
+
+<p> Can be used as a lightweight one-stop-shop for simple XML processing; a simple XML parser is included
+ but the default is to use <code>lxp.lom</code> if it can be found.
+ <pre>
+ Prosody IM
+ Copyright &copy; 2008-2010 Matthew Wild
+ Copyright &copy; 2008-2010 Waqas Hussain&ndash;
+ classic Lua XML parser by Roberto Ierusalimschy.
+ modified to output LOM format.
+ http://lua-users.org/wiki/LuaXml
+ </pre>
+ See <a href="../manual/06-data.md.html#XML">the Guide</a></p>
+
+<p> Dependencies: <a href="../libraries/pl.utils.html#">pl.utils</a></p>
+
+<p> Soft Dependencies: <code>lxp.lom</code> (fallback is to use basic Lua parser)</p>
+
+
+<h2><a href="#Functions">Functions</a></h2>
+<table class="function_list">
+ <tr>
+ <td class="name" nowrap><a href="#new">new (tag, attr)</a></td>
+ <td class="summary">create a new document node.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#parse">parse (text_or_file, is_file, use_basic)</a></td>
+ <td class="summary">parse an XML document.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:addtag">Doc:addtag (tag, attrs)</a></td>
+ <td class="summary">convenient function to add a document node, This updates the last inserted position.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:text">Doc:text (text)</a></td>
+ <td class="summary">convenient function to add a text node.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:up">Doc:up ()</a></td>
+ <td class="summary">go up one level in a document</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:add_direct_child">Doc:add_direct_child (child)</a></td>
+ <td class="summary">append a child to a document directly.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:add_child">Doc:add_child (child)</a></td>
+ <td class="summary">append a child to a document at the last element added</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:set_attribs">Doc:set_attribs (t)</a></td>
+ <td class="summary">set attributes of a document node.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:set_attrib">Doc:set_attrib (a, v)</a></td>
+ <td class="summary">set a single attribute of a document node.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:get_attribs">Doc:get_attribs ()</a></td>
+ <td class="summary">access the attributes of a document node.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#elem">elem (tag, items)</a></td>
+ <td class="summary">function to create an element with a given tag name and a set of children.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#tags">tags (list)</a></td>
+ <td class="summary">given a list of names, return a number of element constructors.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc.subst">Doc.subst (templ, data)</a></td>
+ <td class="summary">create a substituted copy of a document,</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:child_with_name">Doc:child_with_name (tag)</a></td>
+ <td class="summary">get the first child with a given tag name.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:get_elements_with_name">Doc:get_elements_with_name (tag, dont_recurse)</a></td>
+ <td class="summary">get all elements in a document that have a given tag.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:childtags">Doc:childtags ()</a></td>
+ <td class="summary">iterate over all child elements of a document node.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:maptags">Doc:maptags (callback)</a></td>
+ <td class="summary">visit child element of a node and call a function, possibility modifying the document.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#tostring">tostring (t, idn, indent, attr_indent, xml)</a></td>
+ <td class="summary">pretty-print an XML document</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#Doc:get_text">Doc:get_text ()</a></td>
+ <td class="summary">get the full text value of an element</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#clone">clone (doc, strsubst)</a></td>
+ <td class="summary">make a copy of a document</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#compare">compare (t1, t2)</a></td>
+ <td class="summary">compare two documents.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#is_tag">is_tag (d)</a></td>
+ <td class="summary">is this value a document element?</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#walk">walk (doc, depth_first, operation)</a></td>
+ <td class="summary">call the desired function recursively over the document.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#parsehtml">parsehtml (s)</a></td>
+ <td class="summary">Parse a well-formed HTML file as a string.</td>
+ </tr>
+ <tr>
+ <td class="name" nowrap><a href="#basic_parse">basic_parse (s, all_text, html)</a></td>
+ <td class="summary">Parse a simple XML document using a pure Lua parser based on Robero Ierusalimschy&rsquo;s original version.</td>
+ </tr>
+</table>
+
+<br/>
+<br/>
+
+
+ <h2 class="section-header "><a name="Functions"></a>Functions</h2>
+
+ <dl class="function">
+ <dt>
+ <a name = "new"></a>
+ <strong>new (tag, attr)</strong>
+ </dt>
+ <dd>
+ create a new document node.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tag</span>
+ the tag name
+ </li>
+ <li><span class="parameter">attr</span>
+ optional attributes (table of name-value pairs)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "parse"></a>
+ <strong>parse (text_or_file, is_file, use_basic)</strong>
+ </dt>
+ <dd>
+ parse an XML document. By default, this uses lxp.lom.parse, but
+ falls back to basic_parse, or if use_basic is true
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">text_or_file</span>
+ file or string representation
+ </li>
+ <li><span class="parameter">is_file</span>
+ whether text_or_file is a file name or not
+ </li>
+ <li><span class="parameter">use_basic</span>
+ do a basic parse
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+ <li>
+ a parsed LOM document with the document metatatables set</li>
+ <li>
+ nil, error the error can either be a file error or a parse error</li>
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:addtag"></a>
+ <strong>Doc:addtag (tag, attrs)</strong>
+ </dt>
+ <dd>
+ convenient function to add a document node, This updates the last inserted position.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tag</span>
+ a tag name
+ </li>
+ <li><span class="parameter">attrs</span>
+ optional set of attributes (name-string pairs)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:text"></a>
+ <strong>Doc:text (text)</strong>
+ </dt>
+ <dd>
+ convenient function to add a text node. This updates the last inserted position.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">text</span>
+ a string
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:up"></a>
+ <strong>Doc:up ()</strong>
+ </dt>
+ <dd>
+ go up one level in a document
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:add_direct_child"></a>
+ <strong>Doc:add_direct_child (child)</strong>
+ </dt>
+ <dd>
+ append a child to a document directly.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">child</span>
+ a child node (either text or a document)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:add_child"></a>
+ <strong>Doc:add_child (child)</strong>
+ </dt>
+ <dd>
+ append a child to a document at the last element added
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">child</span>
+ a child node (either text or a document)
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:set_attribs"></a>
+ <strong>Doc:set_attribs (t)</strong>
+ </dt>
+ <dd>
+ set attributes of a document node.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ a table containing attribute/value pairs
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:set_attrib"></a>
+ <strong>Doc:set_attrib (a, v)</strong>
+ </dt>
+ <dd>
+ set a single attribute of a document node.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">a</span>
+ attribute
+ </li>
+ <li><span class="parameter">v</span>
+ its value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:get_attribs"></a>
+ <strong>Doc:get_attribs ()</strong>
+ </dt>
+ <dd>
+ access the attributes of a document node.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "elem"></a>
+ <strong>elem (tag, items)</strong>
+ </dt>
+ <dd>
+ function to create an element with a given tag name and a set of children.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tag</span>
+ a tag name
+ </li>
+ <li><span class="parameter">items</span>
+ either text or a table where the hash part is the attributes and the list part is the children.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "tags"></a>
+ <strong>tags (list)</strong>
+ </dt>
+ <dd>
+ given a list of names, return a number of element constructors.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">list</span>
+ a list of names, or a comma-separated string.
+ </li>
+ </ul>
+
+
+
+
+ <h3>Usage:</h3>
+ <ul>
+ <pre class="example"><span class="keyword">local</span> parent,children = doc.tags <span class="string">'parent,children'</span> &lt;br&gt;
+ doc = parent {child <span class="string">'one'</span>, child <span class="string">'two'</span>}</pre>
+ </ul>
+
+</dd>
+ <dt>
+ <a name = "Doc.subst"></a>
+ <strong>Doc.subst (templ, data)</strong>
+ </dt>
+ <dd>
+ create a substituted copy of a document,
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">templ</span>
+ may be a document or a string representation which will be parsed and cached
+ </li>
+ <li><span class="parameter">data</span>
+ a table of name-value pairs or a list of such tables
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ an XML document
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:child_with_name"></a>
+ <strong>Doc:child_with_name (tag)</strong>
+ </dt>
+ <dd>
+ get the first child with a given tag name.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tag</span>
+ the tag name
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:get_elements_with_name"></a>
+ <strong>Doc:get_elements_with_name (tag, dont_recurse)</strong>
+ </dt>
+ <dd>
+ get all elements in a document that have a given tag.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">tag</span>
+ a tag name
+ </li>
+ <li><span class="parameter">dont_recurse</span>
+ optionally only return the immediate children with this tag name
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a list of elements
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:childtags"></a>
+ <strong>Doc:childtags ()</strong>
+ </dt>
+ <dd>
+ iterate over all child elements of a document node.
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:maptags"></a>
+ <strong>Doc:maptags (callback)</strong>
+ </dt>
+ <dd>
+ visit child element of a node and call a function, possibility modifying the document.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">callback</span>
+ a function passed the node (text or element). If it returns nil, that node will be removed.
+ If it returns a value, that will replace the current node.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "tostring"></a>
+ <strong>tostring (t, idn, indent, attr_indent, xml)</strong>
+ </dt>
+ <dd>
+ pretty-print an XML document
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t</span>
+ an XML document
+ </li>
+ <li><span class="parameter">idn</span>
+ an initial indent (indents are all strings)
+ </li>
+ <li><span class="parameter">indent</span>
+ an indent for each level
+ </li>
+ <li><span class="parameter">attr_indent</span>
+ if given, indent each attribute pair and put on a separate line
+ </li>
+ <li><span class="parameter">xml</span>
+ force prefacing with default or custom &lt;?xml&hellip;>
+ </li>
+ </ul>
+
+ <h3>Returns:</h3>
+ <ol>
+
+ a string representation
+ </ol>
+
+
+
+
+</dd>
+ <dt>
+ <a name = "Doc:get_text"></a>
+ <strong>Doc:get_text ()</strong>
+ </dt>
+ <dd>
+ get the full text value of an element
+
+
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "clone"></a>
+ <strong>clone (doc, strsubst)</strong>
+ </dt>
+ <dd>
+ make a copy of a document
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">doc</span>
+ the original document
+ </li>
+ <li><span class="parameter">strsubst</span>
+ an optional function for handling string copying which could do substitution, etc.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "compare"></a>
+ <strong>compare (t1, t2)</strong>
+ </dt>
+ <dd>
+ compare two documents.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">t1</span>
+ any value
+ </li>
+ <li><span class="parameter">t2</span>
+ any value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "is_tag"></a>
+ <strong>is_tag (d)</strong>
+ </dt>
+ <dd>
+ is this value a document element?
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">d</span>
+ any value
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "walk"></a>
+ <strong>walk (doc, depth_first, operation)</strong>
+ </dt>
+ <dd>
+ call the desired function recursively over the document.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">doc</span>
+ the document
+ </li>
+ <li><span class="parameter">depth_first</span>
+ visit child notes first, then the current node
+ </li>
+ <li><span class="parameter">operation</span>
+ a function which will receive the current tag name and current node.
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "parsehtml"></a>
+ <strong>parsehtml (s)</strong>
+ </dt>
+ <dd>
+ Parse a well-formed HTML file as a string.
+ Tags are case-insenstive, DOCTYPE is ignored, and empty elements can be .. empty.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ the HTML
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+ <dt>
+ <a name = "basic_parse"></a>
+ <strong>basic_parse (s, all_text, html)</strong>
+ </dt>
+ <dd>
+ Parse a simple XML document using a pure Lua parser based on Robero Ierusalimschy&rsquo;s original version.
+
+
+ <h3>Parameters:</h3>
+ <ul>
+ <li><span class="parameter">s</span>
+ the XML document to be parsed.
+ </li>
+ <li><span class="parameter">all_text</span>
+ if true, preserves all whitespace. Otherwise only text containing non-whitespace is included.
+ </li>
+ <li><span class="parameter">html</span>
+ if true, uses relaxed HTML rules for parsing
+ </li>
+ </ul>
+
+
+
+
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/01-introduction.md.html b/docs/manual/01-introduction.md.html
new file mode 100644
index 0000000..dbd2d62
--- /dev/null
+++ b/docs/manual/01-introduction.md.html
@@ -0,0 +1,845 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Purpose">Purpose </a></li>
+<li><a href="#To_Inject_or_not_to_Inject_">To Inject or not to Inject? </a></li>
+<li><a href="#What_are_function_arguments_in_Penlight_">What are function arguments in Penlight? </a></li>
+<li><a href="#Pros_and_Cons_of_Loopless_Programming">Pros and Cons of Loopless Programming </a></li>
+<li><a href="#Generally_useful_functions">Generally useful functions </a></li>
+<li><a href="#Application_Support">Application Support </a></li>
+<li><a href="#Simplifying_Object_Oriented_Programming_in_Lua">Simplifying Object-Oriented Programming in Lua </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><strong>Introduction</strong></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Introduction</h2>
+
+<p><a name="Purpose"></a></p>
+
+<h3>Purpose</h3>
+
+<p>It is often said of Lua that it does not include batteries. That is because the
+goal of Lua is to produce a lean expressive language that will be used on all
+sorts of machines, (some of which don&rsquo;t even have hierarchical filesystems). The
+Lua language is the equivalent of an operating system kernel; the creators of Lua
+do not see it as their responsibility to create a full software ecosystem around
+the language. That is the role of the community.</p>
+
+<p>A principle of software design is to recognize common patterns and reuse them. If
+you find yourself writing things like <code>io.write(string.format('the answer is %d
+',42))</code> more than a number of times then it becomes useful just to define a
+function <code>printf</code>. This is good, not just because repeated code is harder to
+maintain, but because such code is easier to read, once people understand your
+libraries.</p>
+
+<p>Penlight captures many such code patterns, so that the intent of your code
+becomes clearer. For instance, a Lua idiom to copy a table is <code>{unpack(t)}</code>, but
+this will only work for &lsquo;small&rsquo; tables (for a given value of &lsquo;small&rsquo;) so it is
+not very robust. Also, the intent is not clear. So <a href="../libraries/pl.tablex.html#deepcopy">tablex.deepcopy</a> is provided,
+which will also copy nested tables and and associated metatables, so it can be
+used to clone complex objects.</p>
+
+<p>The default error handling policy follows that of the Lua standard libraries: if
+a argument is the wrong type, then an error will be thrown, but otherwise we
+return <code>nil,message</code> if there is a problem. There are some exceptions; functions
+like <a href="../libraries/pl.input.html#fields">input.fields</a> default to shutting down the program immediately with a
+useful message. This is more appropriate behaviour for a <em>script</em> than providing
+a stack trace. (However, this default can be changed.) The lexer functions always
+throw errors, to simplify coding, and so should be wrapped in <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pcall">pcall</a>.</p>
+
+<p>If you are used to Python conventions, please note that all indices consistently
+start at 1.</p>
+
+<p>The Lua function <a href="https://www.lua.org/manual/5.1/manual.html#pdf-table.foreach">table.foreach</a> has been deprecated in favour of the <code>for in</code>
+statement, but such an operation becomes particularly useful with the
+higher-order function support in Penlight. Note that <a href="../libraries/pl.tablex.html#foreach">tablex.foreach</a> reverses
+the order, so that the function is passed the value and then the key. Although
+perverse, this matches the intended use better.</p>
+
+<p>The only important external dependence of Penlight is
+<a href="http://keplerproject.github.com/luafilesystem/manual.html">LuaFileSystem</a>
+(<a href="http://stevedonovan.github.io/lua-stdlibs/modules/lfs.html">lfs</a>), and if you want <a href="../libraries/pl.dir.html#copyfile">dir.copyfile</a> to work cleanly on Windows, you will need
+either <a href="http://alien.luaforge.net/">alien</a> or be using
+<a href="http://luajit.org">LuaJIT</a> as well. (The fallback is to call the equivalent
+shell commands.)</p>
+
+<p><a name="To_Inject_or_not_to_Inject_"></a></p>
+
+<h3>To Inject or not to Inject?</h3>
+
+<p>It was realized a long time ago that large programs needed a way to keep names
+distinct by putting them into tables (Lua), namespaces (C++) or modules
+(Python). It is obviously impossible to run a company where everyone is called
+&lsquo;Bruce&rsquo;, except in Monty Python skits. These &lsquo;namespace clashes&rsquo; are more of a
+problem in a simple language like Lua than in C++, because C++ does more
+complicated lookup over &lsquo;injected namespaces&rsquo;. However, in a small group of
+friends, &lsquo;Bruce&rsquo; is usually unique, so in particular situations it&rsquo;s useful to
+drop the formality and not use last names. It depends entirely on what kind of
+program you are writing, whether it is a ten line script or a ten thousand line
+program.</p>
+
+<p>So the Penlight library provides the formal way and the informal way, without
+imposing any preference. You can do it formally like:</p>
+
+<pre>
+<span class="keyword">local</span> utils = <span class="global">require</span> <span class="string">'pl.utils'</span>
+utils.printf(<span class="string">"%s\n"</span>,<span class="string">"hello, world!"</span>)
+</pre>
+
+
+<p>or informally like:</p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+utils.printf(<span class="string">"%s\n"</span>,<span class="string">"That feels better"</span>)
+</pre>
+
+
+<p><code>require &apos;pl&apos;</code> makes all the separate Penlight modules available, without needing
+to require them each individually.</p>
+
+<p>Generally, the formal way is better when writing modules, since then there are no
+global side-effects and the dependencies of your module are made explicit.</p>
+
+<p>Andrew Starks has contributed another way, which balances nicely between the
+formal need to keep the global table uncluttered and the informal need for
+convenience. <code>require&apos;pl.import_into&apos;</code> returns a function, which accepts a table
+for injecting Penlight into, or if no table is given, it passes back a new one.</p>
+
+<pre>
+<span class="keyword">local</span> pl = <span class="global">require</span><span class="string">'pl.import_into'</span>()
+</pre>
+
+
+<p>The table <a href="../libraries/pl.html#">pl</a> is a &lsquo;lazy table&rsquo; which loads modules as needed, so we can then
+use <a href="../libraries/pl.utils.html#printf">pl.utils.printf</a> and so forth, without an explicit `require' or harming any
+globals.</p>
+
+<p>If you are using <code>_ENV</code> with Lua 5.2 to define modules, then here is a way to
+make Penlight available within a module:</p>
+
+<pre>
+<span class="keyword">local</span> _ENV,M = <span class="global">require</span> <span class="string">'pl.import_into'</span> ()
+
+<span class="keyword">function</span> answer ()
+ <span class="comment">-- all the Penlight modules are available!
+</span> <span class="keyword">return</span> pretty.write(utils.split <span class="string">'10 20 30'</span>, <span class="string">''</span>)
+<span class="keyword">end</span>
+
+<span class="keyword">return</span> M
+</pre>
+
+
+<p>The default is to put Penlight into <code>\<em>ENV</code>, which has the unintended effect of
+making it available from the module (much as <code>module(&hellip;,package.seeall)</code> does).
+To satisfy both convenience and safety, you may pass <code>true</code> to this function, and
+then the </em>module<em> <code>M</code> is not the same as <code>\</em>ENV</code>, but only contains the exported
+functions.</p>
+
+<p>Otherwise, Penlight will <em>not</em> bring in functions into the global table, or
+clobber standard tables like &lsquo;io&rsquo;. require(&lsquo;pl&rsquo;) will bring tables like
+&lsquo;utils&rsquo;,&lsquo;tablex&rsquo;,etc into the global table <em>if they are used</em>. This
+&lsquo;load-on-demand&rsquo; strategy ensures that the whole kitchen sink is not loaded up
+front, so this method is as efficient as explicitly loading required modules.</p>
+
+<p>You have an option to bring the <a href="../libraries/pl.stringx.html#">pl.stringx</a> methods into the standard string
+table. All strings have a metatable that allows for automatic lookup in <a href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a>,
+so we can say <code>s:upper()</code>. Importing <a href="../libraries/pl.stringx.html#">stringx</a> allows for its functions to also
+be called as methods: <code>s:strip()</code>,etc:</p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+stringx.import()
+</pre>
+
+
+<p>or, more explicitly:</p>
+
+<pre>
+<span class="global">require</span>(<span class="string">'pl.stringx'</span>).import()
+</pre>
+
+
+<p>A more delicate operation is importing tables into the local environment. This is
+convenient when the context makes the meaning of a name very clear:</p>
+
+<pre>
+&gt; <span class="global">require</span> <span class="string">'pl'</span>
+&gt; utils.import(<span class="global">math</span>)
+&gt; = sin(<span class="number">1.2</span>)
+<span class="number">0.93203908596723</span>
+</pre>
+
+
+<p><a href="../libraries/pl.utils.html#import">utils.import</a> can also be passed a module name as a string, which is first
+required and then imported. If used in a module, <code>import</code> will bring the symbols
+into the module context.</p>
+
+<p>Keeping the global scope simple is very necessary with dynamic languages. Using
+global variables in a big program is always asking for trouble, especially since
+you do not have the spell-checking provided by a compiler. The <a href="../libraries/pl.strict.html#">pl.strict</a>
+module enforces a simple rule: globals must be &lsquo;declared&rsquo;. This means that they
+must be assigned before use; assigning to <code>nil</code> is sufficient.</p>
+
+<pre>
+&gt; <span class="global">require</span> <span class="string">'pl.strict'</span>
+&gt; <span class="global">print</span>(x)
+stdin:<span class="number">1</span>: variable <span class="string">'x'</span> is <span class="keyword">not</span> declared
+&gt; x = <span class="keyword">nil</span>
+&gt; <span class="global">print</span>(x)
+<span class="keyword">nil</span>
+</pre>
+
+
+<p>The <a href="../libraries/pl.strict.html#">strict</a> module provided by Penlight is compatible with the &lsquo;load-on-demand&rsquo;
+scheme used by <code>require &apos;pl</code>.</p>
+
+<p><a href="../libraries/pl.strict.html#">strict</a> also disallows assignment to global variables, except in the main
+program. Generally, modules have no business messing with global scope; if you
+must do it, then use a call to <a href="https://www.lua.org/manual/5.1/manual.html#pdf-rawset">rawset</a>. Similarly, if you have to check for the
+existence of a global, use <a href="https://www.lua.org/manual/5.1/manual.html#pdf-rawget">rawget</a>.</p>
+
+<p>If you wish to enforce strictness globally, then just add <code>require &apos;pl.strict&apos;</code>
+at the end of <code>pl/init.lua</code>, otherwise call it from your main program.</p>
+
+<p>As from 1.1.0, this module provides a <a href="../libraries/pl.strict.html#module">strict.module</a> function which creates (or
+modifies) modules so that accessing an unknown function or field causes an error.</p>
+
+<p>For example,</p>
+
+<pre>
+<span class="comment">-- mymod.lua
+</span><span class="keyword">local</span> strict = <span class="global">require</span> <span class="string">'pl.strict'</span>
+<span class="keyword">local</span> M = strict.<span class="global">module</span> (...)
+
+<span class="keyword">function</span> M.answer ()
+ <span class="keyword">return</span> <span class="number">42</span>
+<span class="keyword">end</span>
+
+<span class="keyword">return</span> M
+</pre>
+
+
+<p>If you were to accidently type <code>mymod.Answer()</code>, then you would get a runtime
+error: &ldquo;variable &lsquo;Answer&rsquo; is not declared in &lsquo;mymod&rsquo;&rdquo;.</p>
+
+<p>This can be applied to existing modules. You may desire to have the same level
+of checking for the Lua standard libraries:</p>
+
+<pre>
+strict.make_all_strict(_G)
+</pre>
+
+
+<p>Thereafter a typo such as <code>math.cosine</code> will give you an explicit error, rather
+than merely returning a <code>nil</code> that will cause problems later.</p>
+
+<p><a name="What_are_function_arguments_in_Penlight_"></a></p>
+
+<h3>What are function arguments in Penlight?</h3>
+
+<p>Many functions in Penlight themselves take function arguments, like <code>map</code> which
+applies a function to a list, element by element. You can use existing
+functions, like <a href="https://www.lua.org/manual/5.1/manual.html#pdf-math.max">math.max</a>, anonymous functions (like <code>function(x,y) return x &gt; y
+end&lt;code&gt; ), or operations by name (e.g &amp;apos;*&amp;apos; or &amp;apos;..&amp;apos;). The module &lt;/code&gt;pl.operator</code> exports
+all the standard Lua operations, like the Python module of the same name.
+Penlight allows these to be referred to by name, so <a href="../libraries/pl.operator.html#gt">operator.gt</a> can be more
+concisely expressed as &lsquo;>&rsquo;.</p>
+
+<p>Note that the <code>map</code> functions pass any extra arguments to the function, so we can
+have <code>ls:filter(&apos;&gt;&apos;,0)</code>, which is a shortcut for
+<code>ls:filter(function(x) return x &gt; 0 end)</code>.</p>
+
+<p>Finally, <a href="../libraries/pl.func.html#">pl.func</a> supports <em>placeholder expressions</em> in the Boost lambda style,
+so that an anonymous function to multiply the two arguments can be expressed as
+<code>\<em>1*\</em>2</code>.</p>
+
+<p>To use them directly, note that <em>all</em> function arguments in Penlight go through
+<a href="../libraries/pl.utils.html#function_arg">utils.function_arg</a>. <a href="../libraries/pl.func.html#">pl.func</a> registers itself with this function, so that you
+can directly use placeholder expressions with standard methods:</p>
+
+<pre>
+&gt; _1 = func._1
+&gt; = List{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}:map(_1+<span class="number">1</span>)
+{<span class="number">11</span>,<span class="number">21</span>,<span class="number">31</span>}
+</pre>
+
+
+<p>Another option for short anonymous functions is provided by
+<a href="../libraries/pl.utils.html#string_lambda">utils.string_lambda</a>; this is invoked automatically:</p>
+
+<pre>
+&gt; = List{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}:map <span class="string">'|x| x + 1'</span>
+{<span class="number">11</span>,<span class="number">21</span>,<span class="number">31</span>}
+</pre>
+
+
+<p><a name="Pros_and_Cons_of_Loopless_Programming"></a></p>
+
+<h3>Pros and Cons of Loopless Programming</h3>
+
+<p>The standard loops-and-ifs &lsquo;imperative&rsquo; style of programming is dominant, and
+often seems to be the &lsquo;natural&rsquo; way of telling a machine what to do. It is in
+fact very much how the machine does things, but we need to take a step back and
+find ways of expressing solutions in a higher-level way. For instance, applying
+a function to all elements of a list is a common operation:</p>
+
+<pre>
+<span class="keyword">local</span> res = {}
+<span class="keyword">for</span> i = <span class="number">1</span>,#ls <span class="keyword">do</span>
+ res[i] = fun(ls[i])
+<span class="keyword">end</span>
+</pre>
+
+
+<p>This can be efficiently and succintly expressed as <code>ls:map(fun)</code>. Not only is
+there less typing but the intention of the code is clearer. If readers of your
+code spend too much time trying to guess your intention by analyzing your loops,
+then you have failed to express yourself clearly. Similarly, <code>ls:filter(&apos;&gt;&apos;,0)</code>
+will give you all the values in a list greater than zero. (Of course, if you
+don&rsquo;t feel like using <a href="../classes/pl.List.html#">List</a>, or have non-list-like tables, then <a href="../libraries/pl.tablex.html#">pl.tablex</a>
+offers the same facilities. In fact, the <a href="../classes/pl.List.html#">List</a> methods are implemented using
+<a href="../libraries/pl.tablex.html#">tablex</a> functions.)</p>
+
+<p>A common observation is that loopless programming is less efficient, particularly
+in the way it uses memory. <code>ls1:map2(&apos;*&apos;,ls2):reduce &apos;+&apos;</code> will give you the dot
+product of two lists, but an unnecessary temporary list is created. But
+efficiency is relative to the actual situation, it may turn out to be <em>fast
+enough</em>, or may not appear in any crucial inner loops, etc.</p>
+
+<p>Writing loops is &lsquo;error-prone and tedious&rsquo;, as Stroustrup says. But any
+half-decent editor can be taught to do much of that typing for you. The question
+should actually be: is it tedious to <em>read</em> loops? As with natural language,
+programmers tend to read chunks at a time. A for-loop causes no surprise, and
+probably little brain activity. One argument for loopless programming is the
+loops that you <em>do</em> write stand out more, and signal &lsquo;something different
+happening here&rsquo;. It should not be an all-or-nothing thing, since most programs
+require a mixture of idioms that suit the problem. Some languages (like APL) do
+nearly everything with map and reduce operations on arrays, and so solutions can
+sometimes seem forced. Wisdom is knowing when a particular idiom makes a
+particular problem easy to <em>solve</em> and the solution easy to <em>explain</em> afterwards.</p>
+
+<p><a name="Generally_useful_functions_"></a></p>
+
+<h3>Generally useful functions.</h3>
+
+<p>The function <code>printf</code> discussed earlier is included in <a href="../libraries/pl.utils.html#">pl.utils</a> because it
+makes properly formatted output easier. (There is an equivalent <code>fprintf</code> which
+also takes a file object parameter, just like the C function.)</p>
+
+<p>Splitting a string using a delimiter is a fairly common operation, hence <code>split</code>.</p>
+
+<p>Utility functions like <code>is_type</code> help with identifying what
+kind of animal you are dealing with.
+The Lua <a href="https://www.lua.org/manual/5.1/manual.html#pdf-type">type</a> function handles the basic types, but can&rsquo;t distinguish between
+different kinds of objects, which are all tables. So <code>is_type</code> handles both
+cases, like <code>is_type(s,&quot;string&quot;)</code> and <code>is_type(ls,List)</code>.</p>
+
+<p>A common pattern when working with Lua varargs is capturing all the arguments in
+a table:</p>
+
+<pre>
+<span class="keyword">function</span> t(...)
+ <span class="keyword">local</span> args = {...}
+ ...
+<span class="keyword">end</span>
+</pre>
+
+
+<p>But this will bite you someday when <code>nil</code> is one of the arguments, since this
+will put a &lsquo;hole&rsquo; in your table. In particular, <code>#ls</code> will only give you the size
+upto the <code>nil</code> value. Hence the need for <a href="https://www.lua.org/manual/5.1/manual.html#pdf-table.pack">table.pack</a> - this is a new Lua 5.2
+function which Penlight defines also for Lua 5.1.</p>
+
+<pre>
+<span class="keyword">function</span> t(...)
+ <span class="keyword">local</span> args,n = <span class="global">table</span>.pack(...)
+ <span class="keyword">for</span> i = <span class="number">1</span>,n <span class="keyword">do</span>
+ ...
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p>The &lsquo;memoize&rsquo; pattern occurs when you have a function which is expensive to call,
+but will always return the same value subsequently. <a href="../libraries/pl.utils.html#memoize">utils.memoize</a> is given a
+function, and returns another function. This calls the function the first time,
+saves the value for that argument, and thereafter for that argument returns the
+saved value. This is a more flexible alternative to building a table of values
+upfront, since in general you won&rsquo;t know what values are needed.</p>
+
+<pre>
+sum = utils.memoize(<span class="keyword">function</span>(n)
+ <span class="keyword">local</span> sum = <span class="number">0</span>
+ <span class="keyword">for</span> i = <span class="number">1</span>,n <span class="keyword">do</span> sum = sum + i <span class="keyword">end</span>
+ <span class="keyword">return</span> sum
+<span class="keyword">end</span>)
+...
+s = sum(<span class="number">1e8</span>) <span class="comment">--takes time!
+</span>...
+s = sum(<span class="number">1e8</span>) <span class="comment">--returned saved value!</span>
+</pre>
+
+
+<p>Penlight is fully compatible with Lua 5.1, 5.2 and LuaJIT 2. To ensure this,
+<a href="../libraries/pl.utils.html#">utils</a> also defines the global Lua 5.2
+<a href="http://www.lua.org/work/doc/manual.html#pdf-load">load</a> function as <a href="../libraries/pl.utils.html#load">utils.load</a></p>
+
+<ul>
+<li>the input (either a string or a function)</li>
+<li>the source name used in debug information</li>
+<li>the mode is a string that can have either or both of &lsquo;b&rsquo; or &rsquo;t', depending on
+whether the source is a binary chunk or text code (default is &lsquo;bt&rsquo;)</li>
+<li>the environment for the compiled chunk</li>
+</ul>
+
+
+<p>Using <a href="../libraries/pl.utils.html#load">utils.load</a> should reduce the need to call the deprecated function <a href="https://www.lua.org/manual/5.1/manual.html#pdf-setfenv">setfenv</a>,
+and make your Lua 5.1 code 5.2-friendly.</p>
+
+<p>The <a href="../libraries/pl.utils.html#">utils</a> module exports <a href="https://www.lua.org/manual/5.1/manual.html#pdf-getfenv">getfenv</a> and <a href="https://www.lua.org/manual/5.1/manual.html#pdf-setfenv">setfenv</a> for
+Lua 5.2 as well, based on code by Sergey Rozhenko. Note that these functions can fail
+for functions which don&rsquo;t access any globals.</p>
+
+<p><a name="Application_Support"></a></p>
+
+<h3>Application Support</h3>
+
+<p><a href="../libraries/pl.app.html#parse_args">app.parse_args</a> is a simple command-line argument parser. If called without any
+arguments, it tries to use the global <code>arg</code> array. It returns the <em>flags</em>
+(options begining with &lsquo;-&rsquo;) as a table of name/value pairs, and the <em>arguments</em>
+as an array. It knows about long GNU-style flag names, e.g. <code>&ndash;value</code>, and
+groups of short flags are understood, so that <code>-ab</code> is short for <code>-a -b</code>. The
+flags result would then look like <code>{value=true,a=true,b=true}</code>.</p>
+
+<p>Flags may take values. The command-line <code>&ndash;value=open -n10</code> would result in
+<code>{value=&apos;open&apos;,n=&apos;10&apos;}</code>; generally you can use &lsquo;=&rsquo; or &lsquo;:&rsquo; to separate the flag
+from its value, except in the special case where a short flag is followed by an
+integer. Or you may specify upfront that some flags have associated values, and
+then the values will follow the flag.</p>
+
+<pre>
+&gt; <span class="global">require</span> <span class="string">'pl'</span>
+&gt; flags,args = app.parse_args({<span class="string">'-o'</span>,<span class="string">'fred'</span>,<span class="string">'-n10'</span>,<span class="string">'fred.txt'</span>},{o=<span class="keyword">true</span>})
+&gt; pretty.dump(flags)
+{o=<span class="string">'fred'</span>,n=<span class="string">'10'</span>}
+</pre>
+
+
+<p><code>parse_args</code> is not intelligent or psychic; it will not convert any flag values
+or arguments for you, or raise errors. For that, have a look at
+<a href="../manual/08-additional.md.html#Command_line_Programs_with_Lapp">Lapp</a>.</p>
+
+<p>An application which consists of several files usually cannot use <a href="https://www.lua.org/manual/5.1/manual.html#pdf-require">require</a> to
+load files in the same directory as the main script. <code>app.require_here()</code>
+ensures that the Lua module path is modified so that files found locally are
+found first. In the <code>examples</code> directory, <a href="../examples/test-symbols.lua.html#">test-symbols.lua</a> uses this function
+to ensure that it can find <a href="../examples/symbols.lua.html#">symbols.lua</a> even if it is not run from this directory.</p>
+
+<p><a href="../libraries/pl.app.html#appfile">app.appfile</a> will create a filename that your application can use to store its
+private data, based on the script name. For example, <code>app.appfile &quot;test.txt&quot;</code>
+from a script called <a href="../examples/testapp.lua.html#">testapp.lua</a> produces the following file on my Windows
+machine:</p>
+
+<pre><code>C:\Documents and Settings\SJDonova\.testapp\test.txt
+</code></pre>
+
+<p>and the equivalent on my Linux machine:</p>
+
+<pre><code>/home/sdonovan/.testapp/test.txt
+</code></pre>
+
+<p>If <code>.testapp</code> does not exist, it will be created.</p>
+
+<p>Penlight makes it convenient to save application data in Lua format. You can use
+<code>pretty.dump(t,file)</code> to write a Lua table in a human-readable form to a file,
+and <code>pretty.read(file.read(file))</code> to generate the table again, using the
+<a href="../libraries/pl.pretty.html#">pretty</a> module.</p>
+
+<p><a name="Simplifying_Object_Oriented_Programming_in_Lua"></a></p>
+
+<h3>Simplifying Object-Oriented Programming in Lua</h3>
+
+<p>Lua is similar to JavaScript in that the concept of class is not directly
+supported by the language. In fact, Lua has a very general mechanism for
+extending the behaviour of tables which makes it straightforward to implement
+classes. A table&rsquo;s behaviour is controlled by its metatable. If that metatable
+has a <code>\<em>\</em>index</code> function or table, this will handle looking up anything which is
+not found in the original table. A class is just a table with an <code>__index</code> key
+pointing to itself. Creating an object involves making a table and setting its
+metatable to the class; then when handling <code>obj.fun</code>, Lua first looks up <code>fun</code> in
+the table <code>obj</code>, and if not found it looks it up in the class. <code>obj:fun(a)</code> is
+just short for <code>obj.fun(obj,a)</code>. So with the metatable mechanism and this bit of
+syntactic sugar, it is straightforward to implement classic object orientation.</p>
+
+<pre>
+<span class="comment">-- animal.lua
+</span>
+class = <span class="global">require</span> <span class="string">'pl.class'</span>
+
+class.Animal()
+
+<span class="keyword">function</span> Animal:_init(name)
+ self.name = name
+<span class="keyword">end</span>
+
+<span class="keyword">function</span> Animal:__tostring()
+ <span class="keyword">return</span> self.name..<span class="string">': '</span>..self:speak()
+<span class="keyword">end</span>
+
+class.Dog(Animal)
+
+<span class="keyword">function</span> Dog:speak()
+ <span class="keyword">return</span> <span class="string">'bark'</span>
+<span class="keyword">end</span>
+
+class.Cat(Animal)
+
+<span class="keyword">function</span> Cat:_init(name,breed)
+ self:super(name) <span class="comment">-- must init base!
+</span> self.breed = breed
+<span class="keyword">end</span>
+
+<span class="keyword">function</span> Cat:speak()
+ <span class="keyword">return</span> <span class="string">'meow'</span>
+<span class="keyword">end</span>
+
+class.Lion(Cat)
+
+<span class="keyword">function</span> Lion:speak()
+ <span class="keyword">return</span> <span class="string">'roar'</span>
+<span class="keyword">end</span>
+
+fido = Dog(<span class="string">'Fido'</span>)
+felix = Cat(<span class="string">'Felix'</span>,<span class="string">'Tabby'</span>)
+leo = Lion(<span class="string">'Leo'</span>,<span class="string">'African'</span>)
+
+$ lua -i animal.lua
+&gt; = fido,felix,leo
+Fido: bark Felix: meow Leo: roar
+&gt; = leo:is_a(Animal)
+<span class="keyword">true</span>
+&gt; = leo:is_a(Dog)
+<span class="keyword">false</span>
+&gt; = leo:is_a(Cat)
+<span class="keyword">true</span>
+</pre>
+
+
+<p>All Animal does is define <code>\<em>\</em>tostring</code>, which Lua will use whenever a string
+representation is needed of the object. In turn, this relies on <code>speak</code>, which is
+not defined. So it&rsquo;s what C++ people would call an abstract base class; the
+specific derived classes like Dog define <code>speak</code>. Please note that <em>if</em> derived
+classes have their own constructors, they must explicitly call the base
+constructor for their base class; this is conveniently available as the <code>super</code>
+method.</p>
+
+<p>Note that (as always) there are multiple ways to implement OOP in Lua; this method
+uses the classic &lsquo;a class is the __index of its objects&rsquo; but does &lsquo;fat inheritance&rsquo;;
+methods from the base class are copied into the new class. The advantage of this is
+that you are not penalized for long inheritance chains, for the price of larger classes,
+but generally objects outnumber classes! (If not, something odd is going on with your design.)</p>
+
+<p>All such objects will have a <code>is_a</code> method, which looks up the inheritance chain
+to find a match. Another form is <code>class_of</code>, which can be safely called on all
+objects, so instead of <code>leo:is_a(Animal)</code> one can say <code>Animal:class_of(leo)</code>.</p>
+
+<p>There are two ways to define a class, either <code>class.Name()</code> or <code>Name = class()</code>;
+both work identically, except that the first form will always put the class in
+the current environment (whether global or module); the second form provides more
+flexibility about where to store the class. The first form does <em>name</em> the class
+by setting the <code>_name</code> field, which can be useful in identifying the objects of
+this type later. This session illustrates the usefulness of having named classes,
+if no <code>__tostring</code> method is explicitly defined.</p>
+
+<pre>
+&gt; class.Fred()
+&gt; a = Fred()
+&gt; = a
+Fred: <span class="number">00459330</span>
+&gt; Alice = class()
+&gt; b = Alice()
+&gt; = b
+<span class="global">table</span>: <span class="number">00459</span>AE8
+&gt; Alice._name = <span class="string">'Alice'</span>
+&gt; = b
+Alice: <span class="number">00459</span>AE8
+</pre>
+
+
+<p>So <code>Alice = class(); Alice._name = &apos;Alice&apos;</code> is exactly the same as <code>class.Alice()</code>.</p>
+
+<p>This useful notation is borrowed from Hugo Etchegoyen&rsquo;s
+<a href="http://lua-users.org/wiki/MultipleInheritanceClasses">classlib</a> which further
+extends this concept to allow for multiple inheritance. Notice that the
+more convenient form puts the class name in the <em>current environment</em>! That is,
+you may use it safely within modules using the old-fashioned <code>module()</code>
+or the new <code>_ENV</code> mechanism.</p>
+
+<p>There is always more than one way of doing things in Lua; some may prefer this
+style for creating classes:</p>
+
+<pre>
+<span class="keyword">local</span> class = <span class="global">require</span> <span class="string">'pl.class'</span>
+
+class.Named {
+ _init = <span class="keyword">function</span>(self,name)
+ self.name = name
+ <span class="keyword">end</span>;
+
+ __tostring = <span class="keyword">function</span>(self)
+ <span class="keyword">return</span> <span class="string">'boo '</span>..self.name
+ <span class="keyword">end</span>;
+}
+
+b = Named <span class="string">'dog'</span>
+<span class="global">print</span>(b)
+<span class="comment">--&gt; boo dog</span>
+</pre>
+
+
+<p>Note that you have to explicitly declare <code>self</code> and end each function definition
+with a semi-colon or comma, since this is a Lua table. To inherit from a base class,
+set the special field <code>_base</code> to the class in this table.</p>
+
+<p>Penlight provides a number of useful classes; there is <a href="../classes/pl.List.html#">List</a>, which is a Lua
+clone of the standard Python list object, and <a href="../libraries/pl.Set.html#">Set</a> which represents sets. There
+are three kinds of <em>map</em> defined: <a href="../classes/pl.Map.html#">Map</a>, <a href="../classes/pl.MultiMap.html#">MultiMap</a> (where a key may have
+multiple values) and <a href="../classes/pl.OrderedMap.html#">OrderedMap</a> (where the order of insertion is remembered.).
+There is nothing special about these classes and you may inherit from them.</p>
+
+<p>A powerful thing about dynamic languages is that you can redefine existing classes
+and functions, which is often called &lsquo;monkey patching&rsquo; It&rsquo;s entertaining and convenient,
+but ultimately anti-social; you may modify <a href="../classes/pl.List.html#">List</a> but then any other modules using
+this <em>shared</em> resource can no longer be sure about its behaviour. (This is why you
+must say <code>stringx.import()</code> explicitly if you want the extended string methods - it
+would be a bad default.) Lua is particularly open to modification but the
+community is not as tolerant of monkey-patching as the Ruby community, say. You may
+wish to add some new methods to <a href="../classes/pl.List.html#">List</a>? Cool, but that&rsquo;s what subclassing is for.</p>
+
+<pre>
+class.Strings(List)
+
+<span class="keyword">function</span> Strings:my_method()
+...
+<span class="keyword">end</span>
+</pre>
+
+
+<p>It&rsquo;s definitely more useful to define exactly how your objects behave
+in <em>unknown</em> conditions. All classes have a <code>catch</code> method you can use to set
+a handler for unknown lookups; the function you pass looks exactly like the
+<code>__index</code> metamethod.</p>
+
+<pre>
+Strings:catch(<span class="keyword">function</span>(self,name)
+ <span class="keyword">return</span> <span class="keyword">function</span>() <span class="global">error</span>(<span class="string">"no such method "</span>..name,<span class="number">2</span>) <span class="keyword">end</span>
+<span class="keyword">end</span>)
+</pre>
+
+
+<p>In this case we&rsquo;re just customizing the error message, but
+creative things can be done. Consider this code from <code>test-vector.lua</code>:</p>
+
+<pre>
+Strings:catch(List.default_map_with(<span class="global">string</span>))
+
+ls = Strings{<span class="string">'one'</span>,<span class="string">'two'</span>,<span class="string">'three'</span>}
+asserteq(ls:upper(),{<span class="string">'ONE'</span>,<span class="string">'TWO'</span>,<span class="string">'THREE'</span>})
+asserteq(ls:sub(<span class="number">1</span>,<span class="number">2</span>),{<span class="string">'on'</span>,<span class="string">'tw'</span>,<span class="string">'th'</span>})
+</pre>
+
+
+<p>So we&rsquo;ve converted a unknown method invocation into a map using the function of
+that name found in <a href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a>. So for a <code>Vector</code> (which is a specialization of <a href="../classes/pl.List.html#">List</a>
+for numbers) it makes sense to make <a href="https://www.lua.org/manual/5.1/manual.html#5.6">math</a> the default map so that <code>v:sin()</code> makes
+sense.</p>
+
+<p>Note that <code>map</code> operations return a object of the same type - this is often called
+<em>covariance</em>. So <code>ls:upper()</code> itself returns a <code>Strings</code> object.</p>
+
+<p>This is not <em>always</em> what you want, but objects can always be cast to the desired type.
+(<code>cast</code> doesn&rsquo;t create a new object, but returns the object passed.)</p>
+
+<pre>
+<span class="keyword">local</span> sizes = ls:map <span class="string">'#'</span>
+asserteq(sizes, {<span class="number">3</span>,<span class="number">3</span>,<span class="number">5</span>})
+asserteq(utils.<span class="global">type</span>(sizes),<span class="string">'Strings'</span>)
+asserteq(sizes:is_a(Strings),<span class="keyword">true</span>)
+sizes = Vector:cast(sizes)
+asserteq(utils.<span class="global">type</span>(sizes),<span class="string">'Vector'</span>)
+asserteq(sizes+<span class="number">1</span>,{<span class="number">4</span>,<span class="number">4</span>,<span class="number">6</span>})
+</pre>
+
+
+<p>About <code>utils.type</code>: it can only return a string for a class type if that class does
+in fact have a <code>_name</code> field.</p>
+
+<p><em>Properties</em> are a useful object-oriented pattern. We wish to control access to a
+field, but don&rsquo;t wish to force the user of the class to say <code>obj:get_field()</code>
+etc. This excerpt from <code>tests/test-class.lua</code> shows how it is done:</p>
+
+<pre>
+<span class="keyword">local</span> MyProps = class(class.properties)
+<span class="keyword">local</span> setted_a, got_b
+
+<span class="keyword">function</span> MyProps:_init ()
+ self._a = <span class="number">1</span>
+ self._b = <span class="number">2</span>
+<span class="keyword">end</span>
+
+<span class="keyword">function</span> MyProps:set_a (v)
+ setted_a = <span class="keyword">true</span>
+ self._a = v
+<span class="keyword">end</span>
+
+<span class="keyword">function</span> MyProps:get_b ()
+ got_b = <span class="keyword">true</span>
+ <span class="keyword">return</span> self._b
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> mp = MyProps()
+
+mp.a = <span class="number">10</span>
+
+asserteq(mp.a,<span class="number">10</span>)
+asserteq(mp.b,<span class="number">2</span>)
+asserteq(setted_a <span class="keyword">and</span> got_b, <span class="keyword">true</span>)
+</pre>
+
+
+<p>The convention is that the internal field name is prefixed with an underscore;
+when reading <code>mp.a</code>, first a check for an explicit <em>getter</em> <code>get_a</code> and then only
+look for <code>_a</code>. Simularly, writing <code>mp.a</code> causes the <em>setter</em> <code>set_a</code> to be used.</p>
+
+<p>This is cool behaviour, but like much Lua metaprogramming, it is not free. Method
+lookup on such objects goes through <code>\<em>\</em>index</code> as before, but now <code>\<em>\</em>index</code> is a
+function which has to explicitly look up methods in the class, before doing any
+property indexing, which is not going to be as fast as field lookup. If however,
+your accessors actually do non-trivial things, then the extra overhead could be
+worth it.</p>
+
+<p>This is not really intended for <em>access control</em> because external code can write
+to <code>mp._a</code> directly. It is possible to have this kind of control in Lua, but it
+again comes with run-time costs.</p>
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/02-arrays.md.html b/docs/manual/02-arrays.md.html
new file mode 100644
index 0000000..9b548ae
--- /dev/null
+++ b/docs/manual/02-arrays.md.html
@@ -0,0 +1,911 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Python_style_Lists">Python-style Lists </a></li>
+<li><a href="#Map_and_Set_classes">Map and Set classes </a></li>
+<li><a href="#Useful_Operations_on_Tables">Useful Operations on Tables </a></li>
+<li><a href="#Operations_on_two_dimensional_tables">Operations on two-dimensional tables </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><strong>Tables and Arrays</strong></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Tables and Arrays</h2>
+
+<p><a id="list"/></p>
+
+<p><a name="Python_style_Lists"></a></p>
+
+<h3>Python-style Lists</h3>
+
+<p>One of the elegant things about Lua is that tables do the job of both lists and
+dicts (as called in Python) or vectors and maps, (as called in C++), and they do
+it efficiently. However, if we are dealing with &lsquo;tables with numerical indices&rsquo;
+we may as well call them lists and look for operations which particularly make
+sense for lists. The Penlight <a href="../classes/pl.List.html#">List</a> class was originally written by Nick Trout
+for Lua 5.0, and translated to 5.1 and extended by myself. It seemed that
+borrowing from Python was a good idea, and this eventually grew into Penlight.</p>
+
+<p>Here is an example showing <a href="../classes/pl.List.html#">List</a> in action; it redefines <code>__tostring</code>, so that
+it can print itself out more sensibly:</p>
+
+<pre>
+&gt; List = <span class="global">require</span> <span class="string">'pl.List'</span> <span class="comment">--&gt; automatic with require 'pl' &lt;---
+</span>&gt; l = List()
+&gt; l:append(<span class="number">10</span>)
+&gt; l:append(<span class="number">20</span>)
+&gt; = l
+{<span class="number">10</span>,<span class="number">20</span>}
+&gt; l:extend {<span class="number">30</span>,<span class="number">40</span>}
+{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>}
+&gt; l:insert(<span class="number">1</span>,<span class="number">5</span>)
+{<span class="number">5</span>,<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>}
+&gt; = l:pop()
+<span class="number">40</span>
+&gt; = l
+{<span class="number">5</span>,<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}
+&gt; = l:index(<span class="number">30</span>)
+<span class="number">4</span>
+&gt; = l:contains(<span class="number">30</span>)
+<span class="keyword">true</span>
+&gt; = l:reverse() <span class="comment">---&gt; note: doesn't make a copy!
+</span>{<span class="number">30</span>,<span class="number">20</span>,<span class="number">10</span>,<span class="number">5</span>}
+</pre>
+
+
+<p>Although methods like <code>sort</code> and <code>reverse</code> operate in-place and change the list,
+they do return the original list. This makes it possible to do <em>method chaining</em>,
+like <code>ls = ls:append(10):append(20):reverse():append(1)</code>. But (and this is an
+important but) no extra copy is made, so <code>ls</code> does not change identity. <a href="../classes/pl.List.html#">List</a>
+objects (like tables) are <em>mutable</em>, unlike strings. If you want a copy of a
+list, then <code>List(ls)</code> will do the job, i.e. it acts like a copy constructor.
+However, if passed any other table, <a href="../classes/pl.List.html#">List</a> will just set the metatable of the
+table and <em>not</em> make a copy.</p>
+
+<p>A particular feature of Python lists is <em>slicing</em>. This is fully supported in
+this version of <a href="../classes/pl.List.html#">List</a>, except we use 1-based indexing. So <a href="../classes/pl.List.html#List:slice">List.slice</a> works
+rather like <a href="https://www.lua.org/manual/5.1/manual.html#pdf-string.sub">string.sub</a>:</p>
+
+<pre>
+&gt; l = List {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>}
+&gt; = l:slice(<span class="number">1</span>,<span class="number">1</span>) <span class="comment">---&gt; note: creates a new list!
+</span>{<span class="number">10</span>}
+&gt; = l:slice(<span class="number">2</span>,<span class="number">2</span>)
+{<span class="number">20</span>}
+&gt; = l:slice(<span class="number">2</span>,<span class="number">3</span>)
+{<span class="number">20</span>,<span class="number">30</span>}
+&gt; = l:slice(<span class="number">2</span>,-<span class="number">2</span>)
+{<span class="number">20</span>,<span class="number">30</span>}
+&gt; = l:slice_assign(<span class="number">2</span>,<span class="number">2</span>,{<span class="number">21</span>,<span class="number">22</span>,<span class="number">23</span>})
+{<span class="number">10</span>,<span class="number">21</span>,<span class="number">22</span>,<span class="number">23</span>,<span class="number">30</span>,<span class="number">40</span>}
+&gt; = l:chop(<span class="number">1</span>,<span class="number">1</span>)
+{<span class="number">21</span>,<span class="number">22</span>,<span class="number">23</span>,<span class="number">30</span>,<span class="number">40</span>}
+</pre>
+
+
+<p>Functions like <code>slice_assign</code> and <code>chop</code> modify the list; the first is equivalent
+to Python<code>l[i1:i2] = seq</code> and the second to <code>del l[i1:i2]</code>.</p>
+
+<p>List objects are ultimately just Lua &lsquo;list-like&rsquo; tables, but they have extra
+operations defined on them, such as equality and concatention. For regular
+tables, equality is only true if the two tables are <em>identical objects</em>, whereas
+two lists are equal if they have the same contents, i.e. that <code>l1[i]==l2[i]</code> for
+all elements.</p>
+
+<pre>
+&gt; l1 = List {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
+&gt; l2 = List {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
+&gt; = l1 == l2
+<span class="keyword">true</span>
+&gt; = l1..l2
+{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
+</pre>
+
+
+<p>The <a href="../classes/pl.List.html#">List</a> constructor can be passed a function. If so, it&rsquo;s assumed that this is
+an iterator function that can be repeatedly called to generate a sequence. One
+such function is <a href="https://www.lua.org/manual/5.1/manual.html#pdf-io.lines">io.lines</a>; the following short, intense little script counts
+the number of lines in standard input:</p>
+
+<pre>
+<span class="comment">-- linecount.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+ls = List(<span class="global">io</span>.lines())
+<span class="global">print</span>(#ls)
+</pre>
+
+
+<p><a href="../classes/pl.List.html#List.iterate">List.iterate</a> captures what <a href="../classes/pl.List.html#">List</a> considers a sequence. In particular, it can
+also iterate over all &lsquo;characters&rsquo; in a string:</p>
+
+<pre>
+&gt; <span class="keyword">for</span> ch <span class="keyword">in</span> List.iterate <span class="string">'help'</span> <span class="keyword">do</span> <span class="global">io</span>.write(ch,<span class="string">' '</span>) <span class="keyword">end</span>
+h e l p &gt;
+</pre>
+
+
+<p>Since the function <code>iterate</code> is used internally by the <a href="../classes/pl.List.html#">List</a> constructor,
+strings can be made into lists of character strings very easily.</p>
+
+<p>There are a number of operations that go beyond the standard Python methods. For
+instance, you can <em>partition</em> a list into a table of sublists using a function.
+In the simplest form, you use a predicate (a function returning a boolean value)
+to partition the list into two lists, one of elements matching and another of
+elements not matching. But you can use any function; if we use <a href="https://www.lua.org/manual/5.1/manual.html#pdf-type">type</a> then the
+keys will be the standard Lua type names.</p>
+
+<pre>
+&gt; ls = List{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>}
+&gt; ops = <span class="global">require</span> <span class="string">'pl.operator'</span>
+&gt; ls:partition(<span class="keyword">function</span>(x) <span class="keyword">return</span> x &gt; <span class="number">2</span> <span class="keyword">end</span>)
+{<span class="keyword">false</span>={<span class="number">1</span>,<span class="number">2</span>},<span class="keyword">true</span>={<span class="number">3</span>,<span class="number">4</span>}}
+&gt; ls = List{<span class="string">'one'</span>,<span class="global">math</span>.sin,List{<span class="number">1</span>},<span class="number">10</span>,<span class="number">20</span>,List{<span class="number">1</span>,<span class="number">2</span>}}
+&gt; ls:partition(<span class="global">type</span>)
+{<span class="keyword">function</span>={<span class="keyword">function</span>: <span class="number">00369110</span>},<span class="global">string</span>={one},number={<span class="number">10</span>,<span class="number">20</span>},<span class="global">table</span>={{<span class="number">1</span>},{<span class="number">1</span>,<span class="number">2</span>}}}
+</pre>
+
+
+<p>This is one <a href="../classes/pl.List.html#">List</a> method which returns a table which is not a <a href="../classes/pl.List.html#">List</a>. Bear in
+mind that you can always call a <a href="../classes/pl.List.html#">List</a> method on a plain table argument, so
+<code>List.partition(t,type)</code> works as expected. But these functions will only operate
+on the array part of the table.</p>
+
+<p>The &lsquo;nominal&rsquo; type of the returned table is <code>pl.Multimap</code>, which describes a mapping
+between keys and multiple values. This does not mean that <code>pl.Multimap</code> is automatically
+loaded whenever you use <code>partition</code> (or <a href="../classes/pl.List.html#">List</a> for that matter); this is one of the
+standard metatables which are only filled out when the appropriate module is loaded.
+This allows tables to be tagged appropriately without causing excessive coupling.</p>
+
+<p>Stacks occur everywhere in computing. <a href="../classes/pl.List.html#">List</a> supports stack-like operations;
+there is already <code>pop</code> (remove and return last value) and <code>append</code> acts like
+<code>push</code> (add a value to the end). <code>push</code> is provided as an alias for <code>append</code>, and
+the other stack operation (size) is simply the size operator <code>#</code>. Queues can
+also be implemented; you use <code>pop</code> to take values out of the queue, and <code>put</code> to
+insert a value at the begining.</p>
+
+<p>You may derive classes from <a href="../classes/pl.List.html#">List</a>, and since the list-returning methods
+are covariant, the result of <code>slice</code> etc will return lists of the derived type,
+not <a href="../classes/pl.List.html#">List</a>. For instance, consider the specialization of a <a href="../classes/pl.List.html#">List</a> type that contains
+numbers in <code>tests/test-list.lua</code>:</p>
+
+<pre>
+n1 = NA{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}
+n2 = NA{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
+ns = n1 + <span class="number">2</span>*n2
+asserteq(ns,{<span class="number">12</span>,<span class="number">24</span>,<span class="number">36</span>})
+min,max = ns:slice(<span class="number">1</span>,<span class="number">2</span>):minmax()
+asserteq(T(min,max),T(<span class="number">12</span>,<span class="number">24</span>))
+asserteq(n1:normalize():sum(),<span class="number">1</span>,<span class="number">1e-8</span>)
+</pre>
+
+
+<p><a name="Map_and_Set_classes"></a></p>
+
+<h3>Map and Set classes</h3>
+
+<p>The <a href="../classes/pl.Map.html#">Map</a> class exposes what Python would call a &lsquo;dict&rsquo; interface, and accesses
+the hash part of the table. The name &lsquo;Map&rsquo; is used to emphasize the interface,
+not the implementation; it is an object which maps keys onto values; <code>m[&apos;alice&apos;]</code>
+or the equivalent <code>m.alice</code> is the access operation. This class also provides
+explicit <code>set</code> and <code>get</code> methods, which are trivial for regular maps but get
+interesting when <a href="../classes/pl.Map.html#">Map</a> is subclassed. The other operation is <code>update</code>, which
+extends a map by copying the keys and values from another table, perhaps
+overwriting existing keys:</p>
+
+<pre>
+&gt; Map = <span class="global">require</span> <span class="string">'pl.Map'</span>
+&gt; m = Map{one=<span class="number">1</span>,two=<span class="number">2</span>}
+&gt; m:update {three=<span class="number">3</span>,four=<span class="number">4</span>,two=<span class="number">20</span>}
+&gt; = m == M{one=<span class="number">1</span>,two=<span class="number">20</span>,three=<span class="number">3</span>,four=<span class="number">4</span>}
+<span class="keyword">true</span>
+</pre>
+
+
+<p>The method <code>values</code> returns a list of the values, and <code>keys</code> returns a list of
+the keys; there is no guarantee of order. <code>getvalues</code> is given a list of keys and
+returns a list of values associated with these keys:</p>
+
+<pre>
+&gt; m = Map{one=<span class="number">1</span>,two=<span class="number">2</span>,three=<span class="number">3</span>}
+&gt; = m:getvalues {<span class="string">'one'</span>,<span class="string">'three'</span>}
+{<span class="number">1</span>,<span class="number">3</span>}
+&gt; = m:getvalues(m:keys()) == m:values()
+<span class="keyword">true</span>
+</pre>
+
+
+<p>When querying the value of a <a href="../classes/pl.Map.html#">Map</a>, it is best to use the <code>get</code> method:</p>
+
+<pre>
+&gt; <span class="global">print</span>(m:get <span class="string">'one'</span>, m:get <span class="string">'two'</span>)
+<span class="number">1</span> <span class="number">2</span>
+</pre>
+
+
+<p>The reason is that <code>m[key]</code> can be ambiguous; due to the current implementation,
+<code>m[&quot;get&quot;]</code> will always succeed, because if a value is not present in the map, it
+will be looked up in the <a href="../classes/pl.Map.html#">Map</a> metatable, which contains a method <code>get</code>. There is
+currently no simple solution to this annoying restriction.</p>
+
+<p>There are some useful classes which inherit from <a href="../classes/pl.Map.html#">Map</a>. An <a href="../classes/pl.OrderedMap.html#">OrderedMap</a> behaves
+like a <a href="../classes/pl.Map.html#">Map</a> but keeps its keys in order if you use its <code>set</code> method to add keys
+and values. Like all the &lsquo;container&rsquo; classes in Penlight, it defines an <code>iter</code>
+method for iterating over its values; this will return the keys and values in the
+order of insertion; the <code>keys</code> and <code>values</code> methods likewise.</p>
+
+<p>A <a href="../classes/pl.MultiMap.html#">MultiMap</a> allows multiple values to be associated with a given key. So <code>set</code>
+(as before) takes a key and a value, but calling it with the same key and a
+different value does not overwrite but adds a new value. <code>get</code> (or using <code>[]</code>)
+will return a list of values.</p>
+
+<p>A <a href="../libraries/pl.Set.html#">Set</a> can be seen as a special kind of <a href="../classes/pl.Map.html#">Map</a>, where all the values are <code>true</code>,
+the keys are the values, and the order is not important. So in this case
+<a href="../libraries/pl.Set.html#values">Set.values</a> is defined to return a list of the keys. Sets can display
+themselves, and the basic operations like <code>union</code> (<code>+</code>) and <code>intersection</code> (<code>*</code>)
+are defined.</p>
+
+<pre>
+&gt; Set = <span class="global">require</span> <span class="string">'pl.Set'</span>
+&gt; = Set{<span class="string">'one'</span>,<span class="string">'two'</span>} == Set{<span class="string">'two'</span>,<span class="string">'one'</span>}
+<span class="keyword">true</span>
+&gt; fruit = Set{<span class="string">'apple'</span>,<span class="string">'banana'</span>,<span class="string">'orange'</span>}
+&gt; = fruit[<span class="string">'banana'</span>]
+<span class="keyword">true</span>
+&gt; = fruit[<span class="string">'hazelnut'</span>]
+<span class="keyword">nil</span>
+&gt; = fruit:values()
+{apple,orange,banana}
+&gt; colours = Set{<span class="string">'red'</span>,<span class="string">'orange'</span>,<span class="string">'green'</span>,<span class="string">'blue'</span>}
+&gt; = fruit,colours
+[apple,orange,banana] [blue,green,orange,red]
+&gt; = fruit+colours
+[blue,green,apple,red,orange,banana]
+&gt; = fruit*colours
+[orange]
+</pre>
+
+
+<p>There are also the functions <a href="../libraries/pl.Set.html#difference">Set.difference</a> and <code>Set.symmetric_difference</code>. The
+first answers the question &lsquo;what fruits are not colours?&rsquo; and the second &lsquo;what
+are fruits and colours but not both?&rsquo;</p>
+
+<pre>
+&gt; = fruit - colours
+[apple,banana]
+&gt; = fruit ^ colours
+[blue,green,apple,red,banana]
+</pre>
+
+
+<p>Adding elements to a set is simply <code>fruit[&apos;peach&apos;] = true</code> and removing is
+<code>fruit[&apos;apple&apos;] = nil</code> . To make this simplicity work properly, the <a href="../libraries/pl.Set.html#">Set</a> class has no
+methods - either you use the operator forms or explicitly use <code>Set.intersect</code>
+etc. In this way we avoid the ambiguity that plagues <a href="../classes/pl.Map.html#">Map</a>.</p>
+
+<p>(See <a href="../classes/pl.Map.html#">pl.Map</a> and <a href="../libraries/pl.Set.html#">pl.Set</a>)</p>
+
+<p><a name="Useful_Operations_on_Tables"></a></p>
+
+<h3>Useful Operations on Tables</h3>
+
+<p>Some notes on terminology: Lua tables are usually <em>list-like</em> (like an array) or
+<em>map-like</em> (like an associative array or dict); they can of course have a
+list-like and a map-like part. Some of the table operations only make sense for
+list-like tables, and some only for map-like tables. (The usual Lua terminology
+is the array part and the hash part of the table, which reflects the actual
+implementation used; it is more accurate to say that a Lua table is an
+associative map which happens to be particularly efficient at acting like an
+array.)</p>
+
+<p>The functions provided in <a href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a> provide all the basic manipulations on Lua
+tables, but as we saw with the <a href="../classes/pl.List.html#">List</a> class, it is useful to build higher-level
+operations on top of those functions. For instance, to copy a table involves this
+kind of loop:</p>
+
+<pre>
+<span class="keyword">local</span> res = {}
+<span class="keyword">for</span> k,v <span class="keyword">in</span> <span class="global">pairs</span>(T) <span class="keyword">do</span>
+ res[k] = v
+<span class="keyword">end</span>
+<span class="keyword">return</span> res
+</pre>
+
+
+<p>The <a href="../libraries/pl.tablex.html#">tablex</a> module provides this as <a href="../libraries/pl.tablex.html#copy">copy</a>, which does a <em>shallow</em> copy of a
+table. There is also <a href="../libraries/pl.tablex.html#deepcopy">deepcopy</a> which goes further than a simple loop in two
+ways; first, it also gives the copy the same metatable as the original (so it can
+copy objects like <a href="../classes/pl.List.html#">List</a> above) and any nested tables will also be copied, to
+arbitrary depth. There is also <a href="../libraries/pl.tablex.html#icopy">icopy</a> which operates on list-like tables, where
+you can set optionally set the start index of the source and destination as well.
+It ensures that any left-over elements will be deleted:</p>
+
+<pre>
+asserteq(icopy({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},{<span class="number">20</span>,<span class="number">30</span>}),{<span class="number">20</span>,<span class="number">30</span>}) <span class="comment">-- start at 1
+</span>asserteq(icopy({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},{<span class="number">20</span>,<span class="number">30</span>},<span class="number">2</span>),{<span class="number">1</span>,<span class="number">20</span>,<span class="number">30</span>}) <span class="comment">-- start at 2
+</span>asserteq(icopy({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},{<span class="number">20</span>,<span class="number">30</span>},<span class="number">2</span>,<span class="number">2</span>),{<span class="number">1</span>,<span class="number">30</span>}) <span class="comment">-- start at 2, copy from 2</span>
+</pre>
+
+
+<p>(This code from the <a href="../libraries/pl.tablex.html#">tablex</a> test module shows the use of <a href="../libraries/pl.test.html#asserteq">pl.test.asserteq</a>)</p>
+
+<p>Whereas, <a href="../libraries/pl.tablex.html#move">move</a> overwrites but does not delete the rest of the destination:</p>
+
+<pre>
+asserteq(move({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},{<span class="number">20</span>,<span class="number">30</span>}),{<span class="number">20</span>,<span class="number">30</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>})
+asserteq(move({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},{<span class="number">20</span>,<span class="number">30</span>},<span class="number">2</span>),{<span class="number">1</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>})
+asserteq(move({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},{<span class="number">20</span>,<span class="number">30</span>},<span class="number">2</span>,<span class="number">2</span>),{<span class="number">1</span>,<span class="number">30</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>})
+</pre>
+
+
+<p>(The difference is somewhat like that between C&rsquo;s <code>strcpy</code> and <code>memmove</code>.)</p>
+
+<p>To summarize, use <a href="../libraries/pl.tablex.html#copy">copy</a> or <a href="../libraries/pl.tablex.html#deepcopy">deepcopy</a> to make a copy of an arbitrary table. To
+copy into a map-like table, use <a href="../libraries/pl.tablex.html#update">update</a>; to copy into a list-like table use
+<a href="../libraries/pl.tablex.html#icopy">icopy</a>, and <a href="../libraries/pl.tablex.html#move">move</a> if you are updating a range in the destination.</p>
+
+<p>To complete this set of operations, there is <a href="../libraries/pl.tablex.html#insertvalues">insertvalues</a> which works like
+<a href="https://www.lua.org/manual/5.1/manual.html#pdf-table.insert">table.insert</a> except that one provides a table of values to be inserted, and
+<a href="../libraries/pl.tablex.html#removevalues">removevalues</a> which removes a range of values.</p>
+
+<pre>
+asserteq(insertvalues({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>},<span class="number">2</span>,{<span class="number">20</span>,<span class="number">30</span>}),{<span class="number">1</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+asserteq(insertvalues({<span class="number">1</span>,<span class="number">2</span>},{<span class="number">3</span>,<span class="number">4</span>}),{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+</pre>
+
+
+<p>Another example:</p>
+
+<pre>
+&gt; T = <span class="global">require</span> <span class="string">'pl.tablex'</span>
+&gt; t = {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>}
+&gt; = T.removevalues(t,<span class="number">2</span>,<span class="number">3</span>)
+{<span class="number">10</span>,<span class="number">40</span>}
+&gt; = T.insertvalues(t,<span class="number">2</span>,{<span class="number">20</span>,<span class="number">30</span>})
+{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>}
+</pre>
+
+
+<p>In a similar spirit to <a href="../libraries/pl.tablex.html#deepcopy">deepcopy</a>, <a href="../libraries/pl.tablex.html#deepcompare">deepcompare</a> will take two tables and return
+true only if they have exactly the same values and structure.</p>
+
+<pre>
+&gt; t1 = {<span class="number">1</span>,{<span class="number">2</span>,<span class="number">3</span>},<span class="number">4</span>}
+&gt; t2 = deepcopy(t1)
+&gt; = t1 == t2
+<span class="keyword">false</span>
+&gt; = deepcompare(t1,t2)
+<span class="keyword">true</span>
+</pre>
+
+
+<p><a href="../libraries/pl.tablex.html#find">find</a> will return the index of a given value in a list-like table. Note that
+like <a href="https://www.lua.org/manual/5.1/manual.html#pdf-string.find">string.find</a> you can specify an index to start searching, so that all
+instances can be found. There is an optional fourth argument, which makes the
+search start at the end and go backwards, so we could define <a href="../libraries/pl.tablex.html#rfind">rfind</a> like so:</p>
+
+<pre>
+<span class="keyword">function</span> rfind(t,val,istart)
+ <span class="keyword">return</span> tablex.find(t,val,istart,<span class="keyword">true</span>)
+<span class="keyword">end</span>
+</pre>
+
+
+<p><a href="../libraries/pl.tablex.html#find">find</a> does a linear search, so it can slow down code that depends on it. If
+efficiency is required for large tables, consider using an <em>index map</em>.
+<a href="../libraries/pl.tablex.html#index_map">index_map</a> will return a table where the keys are the original values of the
+list, and the associated values are the indices. (It is almost exactly the
+representation needed for a <em>set</em>.)</p>
+
+<pre>
+&gt; t = {<span class="string">'one'</span>,<span class="string">'two'</span>,<span class="string">'three'</span>}
+&gt; = tablex.find(t,<span class="string">'two'</span>)
+<span class="number">2</span>
+&gt; = tablex.find(t,<span class="string">'four'</span>)
+<span class="keyword">nil</span>
+&gt; il = tablex.index_map(t)
+&gt; = il[<span class="string">'two'</span>]
+<span class="number">2</span>
+&gt; = il.two
+<span class="number">2</span>
+</pre>
+
+
+<p>A version of <a href="../libraries/pl.tablex.html#index_map">index_map</a> called <a href="../libraries/pl.tablex.html#makeset">makeset</a> is also provided, where the values are
+just <code>true</code>. This is useful because two such sets can be compared for equality
+using <a href="../libraries/pl.tablex.html#deepcompare">deepcompare</a>:</p>
+
+<pre>
+&gt; = deepcompare(makeset {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},makeset {<span class="number">2</span>,<span class="number">1</span>,<span class="number">3</span>})
+<span class="keyword">true</span>
+</pre>
+
+
+<p>Consider the problem of determining the new employees that have joined in a
+period. Assume we have two files of employee names:</p>
+
+<pre>
+(last-month.txt)
+smith,john
+brady,maureen
+mongale,thabo
+
+(this-month.txt)
+smith,john
+smit,johan
+brady,maureen
+mogale,thabo
+van der Merwe,Piet
+</pre>
+
+
+<p>To find out differences, just make the employee lists into sets, like so:</p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+
+<span class="keyword">function</span> read_employees(file)
+ <span class="keyword">local</span> ls = List(<span class="global">io</span>.lines(file)) <span class="comment">-- a list of employees
+</span> <span class="keyword">return</span> tablex.makeset(ls)
+<span class="keyword">end</span>
+
+last = read_employees <span class="string">'last-month.txt'</span>
+this = read_employees <span class="string">'this-month.txt'</span>
+
+<span class="comment">-- who is in this but not in last?
+</span>diff = tablex.difference(this,last)
+
+<span class="comment">-- in a set, the keys are the values...
+</span><span class="keyword">for</span> e <span class="keyword">in</span> <span class="global">pairs</span>(diff) <span class="keyword">do</span> <span class="global">print</span>(e) <span class="keyword">end</span>
+
+<span class="comment">-- *output*
+</span><span class="comment">-- van der Merwe,Piet
+</span><span class="comment">-- smit,johan</span>
+</pre>
+
+
+<p>The <a href="../libraries/pl.tablex.html#difference">difference</a> operation is easy to write and read:</p>
+
+<pre>
+<span class="keyword">for</span> e <span class="keyword">in</span> <span class="global">pairs</span>(this) <span class="keyword">do</span>
+ <span class="keyword">if</span> <span class="keyword">not</span> last[e] <span class="keyword">then</span>
+ <span class="global">print</span>(e)
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p>Using <a href="../libraries/pl.tablex.html#difference">difference</a> here is not that it is a tricky thing to code, it is that you
+are stating your intentions clearly to other readers of your code. (And naturally
+to your future self, in six months time.)</p>
+
+<p><a href="../libraries/pl.tablex.html#find_if">find_if</a> will search a table using a function. The optional third argument is a
+value which will be passed as a second argument to the function. <a href="../libraries/pl.operator.html#">pl.operator</a>
+provides the Lua operators conveniently wrapped as functions, so the basic
+comparison functions are available:</p>
+
+<pre>
+&gt; ops = <span class="global">require</span> <span class="string">'pl.operator'</span>
+&gt; = tablex.find_if({<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>},ops.gt,<span class="number">20</span>)
+<span class="number">3</span> <span class="keyword">true</span>
+</pre>
+
+
+<p>Note that <a href="../libraries/pl.tablex.html#find_if">find_if</a> will also return the <em>actual value</em> returned by the function,
+which of course is usually just <code>true</code> for a boolean function, but any value
+which is not <code>nil</code> and not <code>false</code> can be usefully passed back.</p>
+
+<p><a href="../libraries/pl.tablex.html#deepcompare">deepcompare</a> does a thorough recursive comparison, but otherwise using the
+default equality operator. <a href="../libraries/pl.tablex.html#compare">compare</a> allows you to specify exactly what function
+to use when comparing two list-like tables, and <a href="../libraries/pl.tablex.html#compare_no_order">compare_no_order</a> is true if
+they contain exactly the same elements. Do note that the latter does not need an
+explicit comparison function - in this case the implementation is actually to
+compare the two sets, as above:</p>
+
+<pre>
+&gt; = compare_no_order({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">2</span>,<span class="number">1</span>,<span class="number">3</span>})
+<span class="keyword">true</span>
+&gt; = compare_no_order({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">2</span>,<span class="number">1</span>,<span class="number">3</span>},<span class="string">'=='</span>)
+<span class="keyword">true</span>
+</pre>
+
+
+<p>(Note the special string &lsquo;==&rsquo; above; instead of saying <code>ops.gt</code> or <code>ops.eq</code> we
+can use the strings &lsquo;>&rsquo; or &lsquo;==&rsquo; respectively.)</p>
+
+<p><a href="../libraries/pl.tablex.html#sort">sort</a> and <a href="../libraries/pl.tablex.html#sortv">sortv</a> return iterators that will iterate through the
+sorted elements of a table. <a href="../libraries/pl.tablex.html#sort">sort</a> iterates by sorted key order, and
+<a href="../libraries/pl.tablex.html#sortv">sortv</a> iterates by sorted value order. For example, given a table
+with names and ages, it is trivial to iterate over the elements:</p>
+
+<pre>
+&gt; t = {john=<span class="number">27</span>,jane=<span class="number">31</span>,mary=<span class="number">24</span>}
+&gt; <span class="keyword">for</span> name,age <span class="keyword">in</span> tablex.sort(t) <span class="keyword">do</span> <span class="global">print</span>(name,age) <span class="keyword">end</span>
+jane <span class="number">31</span>
+john <span class="number">27</span>
+mary <span class="number">24</span>
+&gt; <span class="keyword">for</span> name,age <span class="keyword">in</span> tablex.sortv(t) <span class="keyword">do</span> <span class="global">print</span>(name,age) <span class="keyword">end</span>
+mary <span class="number">24</span>
+john <span class="number">27</span>
+jane <span class="number">31</span>
+</pre>
+
+
+<p>There are several ways to merge tables in PL. If they are list-like, then see the
+operations defined by <a href="../classes/pl.List.html#">pl.List</a>, like concatenation. If they are map-like, then
+<a href="../libraries/pl.tablex.html#merge">merge</a> provides two basic operations. If the third arg is false, then the result
+only contains the keys that are in common between the two tables, and if true,
+then the result contains all the keys of both tables. These are in fact
+generalized set union and intersection operations:</p>
+
+<pre>
+&gt; S1 = {john=<span class="number">27</span>,jane=<span class="number">31</span>,mary=<span class="number">24</span>}
+&gt; S2 = {jane=<span class="number">31</span>,jones=<span class="number">50</span>}
+&gt; = tablex.merge(S1, S2, <span class="keyword">false</span>)
+{jane=<span class="number">31</span>}
+&gt; = tablex.merge(S1, S2, <span class="keyword">true</span>)
+{mary=<span class="number">24</span>,jane=<span class="number">31</span>,john=<span class="number">27</span>,jones=<span class="number">50</span>}
+</pre>
+
+
+<p>When working with tables, you will often find yourself writing loops like in the
+first example. Loops are second nature to programmers, but they are often not the
+most elegant and self-describing way of expressing an operation. Consider the
+<a href="../libraries/pl.tablex.html#map">map</a> function, which creates a new table by applying a function to each element
+of the original:</p>
+
+<pre>
+&gt; = map(<span class="global">math</span>.sin, {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+{ <span class="number">0.84</span>, <span class="number">0.91</span>, <span class="number">0.14</span>, -<span class="number">0.76</span>}
+&gt; = map(<span class="keyword">function</span>(x) <span class="keyword">return</span> x*x <span class="keyword">end</span>, {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+{<span class="number">1</span>,<span class="number">4</span>,<span class="number">9</span>,<span class="number">16</span>}
+</pre>
+
+
+<p><a href="../libraries/pl.tablex.html#map">map</a> saves you from writing a loop, and the resulting code is often clearer, as
+well as being shorter. This is not to say that &lsquo;loops are bad&rsquo; (although you will
+hear that from some extremists), just that it&rsquo;s good to capture standard
+patterns. Then the loops you do write will stand out and acquire more significance.</p>
+
+<p><a href="../libraries/pl.tablex.html#pairmap">pairmap</a> is interesting, because the function works with both the key and the
+value.</p>
+
+<pre>
+&gt; t = {fred=<span class="number">10</span>,bonzo=<span class="number">20</span>,alice=<span class="number">4</span>}
+&gt; = pairmap(<span class="keyword">function</span>(k,v) <span class="keyword">return</span> v <span class="keyword">end</span>, t)
+{<span class="number">4</span>,<span class="number">10</span>,<span class="number">20</span>}
+&gt; = pairmap(<span class="keyword">function</span>(k,v) <span class="keyword">return</span> k <span class="keyword">end</span>, t)
+{<span class="string">'alice'</span>,<span class="string">'fred'</span>,<span class="string">'bonzo'</span>}
+</pre>
+
+
+<p>(These are common enough operations that the first is defined as <a href="../libraries/pl.tablex.html#values">values</a> and the
+second as <a href="../libraries/pl.tablex.html#keys">keys</a>.) If the function returns two values, then the <em>second</em> value is
+considered to be the new key:</p>
+
+<pre>
+&gt; = pairmap(t,<span class="keyword">function</span>(k,v) <span class="keyword">return</span> v+<span class="number">10</span>, k:upper() <span class="keyword">end</span>)
+{BONZO=<span class="number">30</span>,FRED=<span class="number">20</span>,ALICE=<span class="number">14</span>}
+</pre>
+
+
+<p><a href="../libraries/pl.tablex.html#map2">map2</a> applies a function to two tables:</p>
+
+<pre>
+&gt; map2(ops.add,{<span class="number">1</span>,<span class="number">2</span>},{<span class="number">10</span>,<span class="number">20</span>})
+{<span class="number">11</span>,<span class="number">22</span>}
+&gt; map2(<span class="string">'*'</span>,{<span class="number">1</span>,<span class="number">2</span>},{<span class="number">10</span>,<span class="number">20</span>})
+{<span class="number">10</span>,<span class="number">40</span>}
+</pre>
+
+
+<p>The various map operations generate tables; <a href="../libraries/pl.tablex.html#reduce">reduce</a> applies a function of two
+arguments over a table and returns the result as a scalar:</p>
+
+<pre>
+&gt; reduce (<span class="string">'+'</span>, {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>})
+<span class="number">6</span>
+&gt; reduce (<span class="string">'..'</span>, {<span class="string">'one'</span>,<span class="string">'two'</span>,<span class="string">'three'</span>})
+<span class="string">'onetwothree'</span>
+</pre>
+
+
+<p>Finally, <a href="../libraries/pl.tablex.html#zip">zip</a> sews different tables together:</p>
+
+<pre>
+&gt; = zip({<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>})
+{{<span class="number">1</span>,<span class="number">10</span>},{<span class="number">2</span>,<span class="number">20</span>},{<span class="number">3</span>,<span class="number">30</span>}}
+</pre>
+
+
+<p>Browsing through the documentation, you will find that <a href="../libraries/pl.tablex.html#">tablex</a> and <a href="../classes/pl.List.html#">List</a> share
+methods. For instance, <a href="../libraries/pl.tablex.html#imap">tablex.imap</a> and <a href="../classes/pl.List.html#List:map">List.map</a> are basically the same
+function; they both operate over the array-part of the table and generate another
+table. This can also be expressed as a <em>list comprehension</em> <code>C &apos;f(x) for x&apos; (t)</code>
+which makes the operation more explicit. So why are there different ways to do
+the same thing? The main reason is that not all tables are Lists: the expression
+<code>ls:map(&apos;#&apos;)</code> will return a <em>list</em> of the lengths of any elements of <code>ls</code>. A list
+is a thin wrapper around a table, provided by the metatable <a href="../classes/pl.List.html#">List</a>. Sometimes you
+may wish to work with ordinary Lua tables; the <a href="../classes/pl.List.html#">List</a> interface is not a
+compulsory way to use Penlight table operations.</p>
+
+<p><a name="Operations_on_two_dimensional_tables"></a></p>
+
+<h3>Operations on two-dimensional tables</h3>
+
+<p>Two-dimensional tables are of course easy to represent in Lua, for instance
+<code>{{1,2},{3,4}}</code> where we store rows as subtables and index like so <code>A[col][row]</code>.
+This is the common representation used by matrix libraries like
+<a href="http://lua-users.org/wiki/LuaMatrix">LuaMatrix</a>. <a href="../libraries/pl.array2d.html#">pl.array2d</a> does not provide
+matrix operations, since that is the job for a specialized library, but rather
+provides generalizations of the higher-level operations provided by <a href="../libraries/pl.tablex.html#">pl.tablex</a>
+for one-dimensional arrays.</p>
+
+<p><a href="../libraries/pl.array2d.html#iter">iter</a> is a useful generalization of <a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a>. (The extra parameter determines
+whether you want the indices as well.)</p>
+
+<pre>
+&gt; a = {{<span class="number">1</span>,<span class="number">2</span>},{<span class="number">3</span>,<span class="number">4</span>}}
+&gt; <span class="keyword">for</span> i,j,v <span class="keyword">in</span> array2d.iter(a,<span class="keyword">true</span>) <span class="keyword">do</span> <span class="global">print</span>(i,j,v) <span class="keyword">end</span>
+<span class="number">1</span> <span class="number">1</span> <span class="number">1</span>
+<span class="number">1</span> <span class="number">2</span> <span class="number">2</span>
+<span class="number">2</span> <span class="number">1</span> <span class="number">3</span>
+<span class="number">2</span> <span class="number">2</span> <span class="number">4</span>
+</pre>
+
+
+<p>Note that you can always convert an arbitrary 2D array into a &lsquo;list of lists&rsquo;
+with <code>List(tablex.map(List,a))</code></p>
+
+<p><a href="../libraries/pl.array2d.html#map">map</a> will apply a function over all elements (notice that extra arguments can be
+provided, so this operation is in effect <code>function(x) return x-1 end</code>)</p>
+
+<pre>
+&gt; array2d.map(<span class="string">'-'</span>,a,<span class="number">1</span>)
+{{<span class="number">0</span>,<span class="number">1</span>},{<span class="number">2</span>,<span class="number">3</span>}}
+</pre>
+
+
+<p>2D arrays are stored as an array of rows, but columns can be extracted:</p>
+
+<pre>
+&gt; array2d.column(a,<span class="number">1</span>)
+{<span class="number">1</span>,<span class="number">3</span>}
+</pre>
+
+
+<p>There are three equivalents to <a href="../libraries/pl.tablex.html#reduce">tablex.reduce</a>. You can either reduce along the
+rows (which is the most efficient) or reduce along the columns. Either one will
+give you a 1D array. And <a href="../libraries/pl.array2d.html#reduce2">reduce2</a> will apply two operations: the first one
+reduces the rows, and the second reduces the result.</p>
+
+<pre>
+&gt; array2d.reduce_rows(<span class="string">'+'</span>,a)
+{<span class="number">3</span>,<span class="number">7</span>}
+&gt; array2d.reduce_cols(<span class="string">'+'</span>,a)
+{<span class="number">4</span>,<span class="number">6</span>}
+&gt; <span class="comment">-- same as tablex.reduce('*',array.reduce_rows('+',a))
+</span>&gt; array2d.reduce2(<span class="string">'*'</span>,<span class="string">'+'</span>,a)
+<span class="number">21</span> `
+</pre>
+
+
+<p><a href="../libraries/pl.tablex.html#map2">tablex.map2</a> applies an operation to two tables, giving another table.
+<a href="../libraries/pl.array2d.html#map2">array2d.map2</a> does this for 2D arrays. Note that you have to provide the <em>rank</em>
+of the arrays involved, since it&rsquo;s hard to always correctly deduce this from the
+data:</p>
+
+<pre>
+&gt; b = {{<span class="number">10</span>,<span class="number">20</span>},{<span class="number">30</span>,<span class="number">40</span>}}
+&gt; a = {{<span class="number">1</span>,<span class="number">2</span>},{<span class="number">3</span>,<span class="number">4</span>}}
+&gt; = array2d.map2(<span class="string">'+'</span>,<span class="number">2</span>,<span class="number">2</span>,a,b) <span class="comment">-- two 2D arrays
+</span>{{<span class="number">11</span>,<span class="number">22</span>},{<span class="number">33</span>,<span class="number">44</span>}}
+&gt; = array2d.map2(<span class="string">'+'</span>,<span class="number">1</span>,<span class="number">2</span>,{<span class="number">10</span>,<span class="number">100</span>},a) <span class="comment">-- 1D, 2D
+</span>{{<span class="number">11</span>,<span class="number">102</span>},{<span class="number">13</span>,<span class="number">104</span>}}
+&gt; = array2d.map2(<span class="string">'*'</span>,<span class="number">2</span>,<span class="number">1</span>,a,{<span class="number">1</span>,-<span class="number">1</span>}) <span class="comment">-- 2D, 1D
+</span>{{<span class="number">1</span>,-<span class="number">2</span>},{<span class="number">3</span>,-<span class="number">4</span>}}
+</pre>
+
+
+<p>Of course, you are not limited to simple arithmetic. Say we have a 2D array of
+strings, and wish to print it out with proper right justification. The first step
+is to create all the string lengths by mapping <a href="https://www.lua.org/manual/5.1/manual.html#pdf-string.len">string.len</a> over the array, the
+second is to reduce this along the columns using <a href="https://www.lua.org/manual/5.1/manual.html#pdf-math.max">math.max</a> to get maximum column
+widths, and last, apply <a href="../libraries/pl.stringx.html#rjust">stringx.rjust</a> with these widths.</p>
+
+<pre>
+maxlens = reduce_cols(<span class="global">math</span>.max,map(<span class="string">'#'</span>,lines))
+lines = map2(stringx.rjust,<span class="number">2</span>,<span class="number">1</span>,lines,maxlens)
+</pre>
+
+
+<p>There is <a href="../libraries/pl.array2d.html#product">product</a> which returns the <em>Cartesian product</em> of two 1D arrays. The
+result is a 2D array formed from applying the function to all possible pairs from
+the two arrays.</p>
+
+<pre>
+&gt; array2d.product(<span class="string">'{}'</span>,{<span class="number">1</span>,<span class="number">2</span>},{<span class="string">'a'</span>,<span class="string">'b'</span>})
+{{{<span class="number">1</span>,<span class="string">'b'</span>},{<span class="number">2</span>,<span class="string">'a'</span>}},{{<span class="number">1</span>,<span class="string">'a'</span>},{<span class="number">2</span>,<span class="string">'b'</span>}}}
+</pre>
+
+
+<p>There is a set of operations which work in-place on 2D arrays. You can
+<a href="../libraries/pl.array2d.html#swap_rows">swap_rows</a> and <a href="../libraries/pl.array2d.html#swap_cols">swap_cols</a>; the first really is a simple one-liner, but the idea
+here is to give the operation a name. <a href="../libraries/pl.array2d.html#remove_row">remove_row</a> and <a href="../libraries/pl.array2d.html#remove_col">remove_col</a> are
+generalizations of <a href="https://www.lua.org/manual/5.1/manual.html#pdf-table.remove">table.remove</a>. Likewise, <a href="../libraries/pl.array2d.html#extract_rows">extract_rows</a> and <a href="../libraries/pl.array2d.html#extract_cols">extract_cols</a>
+are given arrays of indices and discard anything else. So, for instance,
+<code>extract_cols(A,{2,4})</code> will leave just columns 2 and 4 in the array.</p>
+
+<p><a href="../classes/pl.List.html#List:slice">List.slice</a> is often useful on 1D arrays; <a href="../libraries/pl.array2d.html#slice">slice</a> does the same thing, but is
+generally given a start (row,column) and a end (row,column).</p>
+
+<pre>
+&gt; A = {{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>},{<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>},{<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>}}
+&gt; B = slice(A,<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">2</span>)
+&gt; write(B)
+ <span class="number">1</span> <span class="number">2</span>
+ <span class="number">4</span> <span class="number">5</span>
+&gt; B = slice(A,<span class="number">2</span>,<span class="number">2</span>)
+&gt; write(B,<span class="keyword">nil</span>,<span class="string">'%4.1f'</span>)
+ <span class="number">5.0</span> <span class="number">6.0</span>
+ <span class="number">8.0</span> <span class="number">9.0</span>
+</pre>
+
+
+<p>Here <a href="../libraries/pl.array2d.html#write">write</a> is used to print out an array nicely; the second parameter is <code>nil</code>,
+which is the default (stdout) but can be any file object and the third parameter
+is an optional format (as used in <a href="https://www.lua.org/manual/5.1/manual.html#pdf-string.format">string.format</a>).</p>
+
+<p><a href="../libraries/pl.array2d.html#parse_range">parse_range</a> will take a spreadsheet range like &lsquo;A1:B2&rsquo; or &lsquo;R1C1:R2C2&rsquo; and
+return the range as four numbers, which can be passed to <a href="../libraries/pl.array2d.html#slice">slice</a>. The rule is
+that <a href="../libraries/pl.array2d.html#slice">slice</a> will return an array of the appropriate shape depending on the
+range; if a range represents a row or a column, the result is 1D, otherwise 2D.</p>
+
+<p>This applies to <a href="../libraries/pl.array2d.html#iter">iter</a> as well, which can also optionally be given a range:</p>
+
+<pre>
+&gt; <span class="keyword">for</span> i,j,v <span class="keyword">in</span> iter(A,<span class="keyword">true</span>,<span class="number">2</span>,<span class="number">2</span>) <span class="keyword">do</span> <span class="global">print</span>(i,j,v) <span class="keyword">end</span>
+<span class="number">2</span> <span class="number">2</span> <span class="number">5</span>
+<span class="number">2</span> <span class="number">3</span> <span class="number">6</span>
+<span class="number">3</span> <span class="number">2</span> <span class="number">8</span>
+<span class="number">3</span> <span class="number">3</span> <span class="number">9</span>
+</pre>
+
+
+<p><a href="../libraries/pl.array2d.html#new">new</a> will construct a new 2D array with the given dimensions. You provide an
+initial value for the elements, which is interpreted as a function if it&rsquo;s
+callable. With <code>L</code> being <a href="../libraries/pl.utils.html#string_lambda">utils.string_lambda</a> we then have the following way to
+make an <em>identity matrix</em>:</p>
+
+<pre>
+asserteq(
+ array.new(<span class="number">3</span>,<span class="number">3</span>,L<span class="string">'|i,j| i==j and 1 or 0'</span>),
+ {{<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>},{<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>},{<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>}}
+)
+</pre>
+
+
+<p>Please note that most functions in <a href="../libraries/pl.array2d.html#">array2d</a> are <em>covariant</em>, that is, they
+return an array of the same type as they receive. In particular, any objects
+created with <a href="../libraries/pl.data.html#new">data.new</a> or <code>matrix.new</code> will remain data or matrix objects when
+reshaped or sliced, etc. Data objects have the <a href="../libraries/pl.array2d.html#">array2d</a> functions available as
+methods.</p>
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/03-strings.md.html b/docs/manual/03-strings.md.html
new file mode 100644
index 0000000..987a49d
--- /dev/null
+++ b/docs/manual/03-strings.md.html
@@ -0,0 +1,397 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Extra_String_Methods">Extra String Methods </a></li>
+<li><a href="#String_Templates">String Templates </a></li>
+<li><a href="#Another_Style_of_Template">Another Style of Template </a></li>
+<li><a href="#File_style_I_O_on_Strings">File-style I/O on Strings </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><strong>Strings. Higher-level operations on strings.</strong></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Strings. Higher-level operations on strings.</h2>
+
+<p><a name="Extra_String_Methods"></a></p>
+
+<h3>Extra String Methods</h3>
+
+<p>These are convenient borrowings from Python, as described in 3.6.1 of the Python
+reference, but note that indices in Lua always begin at one. <a href="../libraries/pl.stringx.html#">stringx</a> defines
+functions like <a href="../libraries/pl.stringx.html#isalpha">isalpha</a> and <a href="../libraries/pl.stringx.html#isdigit">isdigit</a>, which return <code>true</code> if s is only composed
+of letters or digits respectively. <a href="../libraries/pl.stringx.html#startswith">startswith</a> and <a href="../libraries/pl.stringx.html#endswith">endswith</a> are convenient
+ways to find substrings. (<a href="../libraries/pl.stringx.html#endswith">endswith</a> works as in Python 2.5, so that <code>f:endswith
+{'.bat','.exe','.cmd'}</code> will be true for any filename which ends with these
+extensions.) There are justify methods and whitespace trimming functions like
+<a href="../libraries/pl.stringx.html#strip">strip</a>.</p>
+
+<pre>
+&gt; stringx.import()
+&gt; (<span class="string">'bonzo.dog'</span>):endswith {<span class="string">'.dog'</span>,<span class="string">'.cat'</span>}
+<span class="keyword">true</span>
+&gt; (<span class="string">'bonzo.txt'</span>):endswith {<span class="string">'.dog'</span>,<span class="string">'.cat'</span>}
+<span class="keyword">false</span>
+&gt; (<span class="string">'bonzo.cat'</span>):endswith {<span class="string">'.dog'</span>,<span class="string">'.cat'</span>}
+<span class="keyword">true</span>
+&gt; (<span class="string">' stuff'</span>):ljust(<span class="number">20</span>,<span class="string">'+'</span>)
+<span class="string">'++++++++++++++ stuff'</span>
+&gt; (<span class="string">' stuff '</span>):lstrip()
+<span class="string">'stuff '</span>
+&gt; (<span class="string">' stuff '</span>):rstrip()
+<span class="string">' stuff'</span>
+&gt; (<span class="string">' stuff '</span>):strip()
+<span class="string">'stuff'</span>
+&gt; <span class="keyword">for</span> s <span class="keyword">in</span> (<span class="string">'one\ntwo\nthree\n'</span>):lines() <span class="keyword">do</span> <span class="global">print</span>(s) <span class="keyword">end</span>
+one
+two
+three
+</pre>
+
+
+<p>Most of these can be fairly easily implemented using the Lua string library,
+which is more general and powerful. But they are convenient operations to have
+easily at hand. Note that can be injected into the <a href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> table if you use
+<code>stringx.import</code>, but a simple alias like <code>local stringx = require &apos;pl.stringx&apos;</code>
+is preferrable. This is the recommended practice when writing modules for
+consumption by other people, since it is bad manners to change the global state
+of the rest of the system. Magic may be used for convenience, but there is always
+a price.</p>
+
+<p><a name="String_Templates"></a></p>
+
+<h3>String Templates</h3>
+
+<p>Another borrowing from Python, string templates allow you to substitute values
+looked up in a table:</p>
+
+<pre>
+<span class="keyword">local</span> Template = <span class="global">require</span> (<span class="string">'pl.text'</span>).Template
+t = Template(<span class="string">'${here} is the $answer'</span>)
+<span class="global">print</span>(t:substitute {here = <span class="string">'Lua'</span>, answer = <span class="string">'best'</span>})
+==&gt;
+Lua is the best
+</pre>
+
+
+<p>&lsquo;$ variables&rsquo; can optionally have curly braces; this form is useful if you are
+glueing text together to make variables, e.g <code>${prefix}_name_${postfix}</code>. The
+<a href="../libraries/pl.text.html#Template:substitute">substitute</a> method will throw an error if a $ variable is not found in the
+table, and the <a href="../libraries/pl.text.html#Template:safe_substitute">safe_substitute</a> method will not.</p>
+
+<p>The Lua implementation has an extra method, <a href="../libraries/pl.text.html#Template:indent_substitute">indent_substitute</a> which is very
+useful for inserting blocks of text, because it adjusts indentation. Consider
+this example:</p>
+
+<pre>
+<span class="comment">-- testtemplate.lua
+</span><span class="keyword">local</span> Template = <span class="global">require</span> (<span class="string">'pl.text'</span>).Template
+
+t = Template <span class="string">[[
+ for i = 1,#$t do
+ $body
+ end
+]]</span>
+
+body = Template <span class="string">[[
+local row = $t[i]
+for j = 1,#row do
+ fun(row[j])
+end
+]]</span>
+
+<span class="global">print</span>(t:indent_substitute {body=body,t=<span class="string">'tbl'</span>})
+</pre>
+
+
+<p>And the output is:</p>
+
+<pre>
+<span class="keyword">for</span> i = <span class="number">1</span>,#tbl <span class="keyword">do</span>
+ <span class="keyword">local</span> row = tbl[i]
+ <span class="keyword">for</span> j = <span class="number">1</span>,#row <span class="keyword">do</span>
+ fun(row[j])
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p><a href="../libraries/pl.text.html#Template:indent_substitute">indent_substitute</a> can substitute templates, and in which case they themselves
+will be substituted using the given table. So in this case, <code>$t</code> was substituted
+twice.</p>
+
+<p><a href="../libraries/pl.text.html#">pl.text</a> also has a number of useful functions like <a href="../libraries/pl.text.html#dedent">dedent</a>, which strips all
+the initial indentation from a multiline string. As in Python, this is useful for
+preprocessing multiline strings if you like indenting them with your code. The
+function <a href="../libraries/pl.text.html#wrap">wrap</a> is passed a long string (a <em>paragraph</em>) and returns a list of
+lines that fit into a desired line width. As an extension, there is also <a href="../libraries/pl.text.html#indent">indent</a>
+for indenting multiline strings.</p>
+
+<p>New in Penlight with the 0.9 series is <code>text.format_operator</code>. Calling this
+enables Python-style string formating using the modulo operator <code>%</code>:</p>
+
+<pre>
+&gt; text.format_operator()
+&gt; = <span class="string">'%s[%d]'</span> % {<span class="string">'dog'</span>,<span class="number">1</span>}
+dog[<span class="number">1</span>]
+</pre>
+
+
+<p>So in its simplest form it saves the typing involved with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-string.format">string.format</a>; it
+will also expand <code>$</code> variables using named fields:</p>
+
+<pre>
+&gt; = <span class="string">'$animal[$num]'</span> % {animal=<span class="string">'dog'</span>,num=<span class="number">1</span>}
+dog[<span class="number">1</span>]
+</pre>
+
+
+<p>As with <code>stringx.import</code> you have to do this explicitly, since all strings share the same
+metatable. But in your own scripts you can feel free to do this.</p>
+
+<p><a name="Another_Style_of_Template"></a></p>
+
+<h3>Another Style of Template</h3>
+
+<p>A new module is <a href="../libraries/pl.template.html#">template</a>, which is a version of Rici Lake&rsquo;s <a href="http://lua-users.org/wiki/SlightlyLessSimpleLuaPreprocessor">Lua
+Preprocessor</a>. This
+allows you to mix Lua code with your templates in a straightforward way. There
+are only two rules:</p>
+
+<ul>
+<li>Lines begining with <code>#</code> are Lua</li>
+<li>Otherwise, anything inside <code>$()</code> is a Lua expression.</li>
+</ul>
+
+
+<p>So a template generating an HTML list would look like this:</p>
+
+<pre>
+&lt;ul&gt;
+# <span class="keyword">for</span> i,val <span class="keyword">in</span> <span class="global">ipairs</span>(T) <span class="keyword">do</span>
+&lt;li&gt;$(i) = $(val:upper())&lt;/li&gt;
+# <span class="keyword">end</span>
+&lt;/ul&gt;
+</pre>
+
+
+<p>Assume the text is inside <code>tmpl</code>, then the template can be expanded using:</p>
+
+<pre>
+<span class="keyword">local</span> template = <span class="global">require</span> <span class="string">'pl.template'</span>
+<span class="keyword">local</span> my_env = {
+ <span class="global">ipairs</span> = <span class="global">ipairs</span>,
+ T = {<span class="string">'one'</span>,<span class="string">'two'</span>,<span class="string">'three'</span>}
+}
+res = template.substitute(tmpl, my_env)
+</pre>
+
+
+<p>and we get</p>
+
+<pre>
+&lt;ul&gt;
+&lt;li&gt;<span class="number">1</span> = ONE&lt;/li&gt;
+&lt;li&gt;<span class="number">2</span> = TWO&lt;/li&gt;
+&lt;li&gt;<span class="number">3</span> = THREE&lt;/li&gt;
+&lt;/ul&gt;
+</pre>
+
+
+<p>There is a single function, <a href="../libraries/pl.template.html#substitute">template.substitute</a> which is passed a template
+string and an environment table. This table may contain some special fields,
+like <code>\<em>parent</code> which can be set to a table representing a &lsquo;fallback&rsquo; environment
+in case a symbol was not found. <code>\</em>brackets</code> is usually &lsquo;()&rsquo; and <code>\_escape</code> is
+usually &lsquo;#&rsquo; but it&rsquo;s sometimes necessary to redefine these if the defaults
+interfere with the target language - for instance, <code>$(V)</code> has another meaning in
+Make, and <code>#</code> means a preprocessor line in C/C++.</p>
+
+<p>Finally, if something goes wrong, passing <code>_debug</code> will cause the intermediate
+Lua code to be dumped if there&rsquo;s a problem.</p>
+
+<p>Here is a C code generation example; something that could easily be extended to
+be a minimal Lua extension skeleton generator.</p>
+
+<pre>
+<span class="keyword">local</span> subst = <span class="global">require</span> <span class="string">'pl.template'</span>.substitute
+
+<span class="keyword">local</span> templ = <span class="string">[[
+#include &lt;lua.h&gt;
+#include &lt;lauxlib.h&gt;
+#include &lt;lualib.h&gt;
+
+&gt; for _,f in ipairs(mod) do
+static int l_$(f.name) (lua_State *L) {
+
+}
+&gt; end
+
+static const luaL_reg $(mod.name)[] = {
+&gt; for _,f in ipairs(mod) do
+ {"$(f.name)",l_$(f.name)},
+&gt; end
+ {NULL,NULL}
+};
+
+int luaopen_$(mod.name) {
+ luaL_register (L, "$(mod.name)", $(mod.name));
+ return 1;
+}
+]]</span>
+
+<span class="global">print</span>(subst(templ,{
+ _escape = <span class="string">'&gt;'</span>,
+ <span class="global">ipairs</span> = <span class="global">ipairs</span>,
+ mod = {
+ name = <span class="string">'baggins'</span>;
+ {name=<span class="string">'frodo'</span>},
+ {name=<span class="string">'bilbo'</span>}
+ }
+}))
+</pre>
+
+
+<p><a name="File_style_I_O_on_Strings"></a></p>
+
+<h3>File-style I/O on Strings</h3>
+
+<p><a href="../libraries/pl.stringio.html#">pl.stringio</a> provides just three functions; <a href="../libraries/pl.stringio.html#open">stringio.open</a> is passed a string,
+and returns a file-like object for reading. It supports a <code>read</code> method, which
+takes the same arguments as standard file objects:</p>
+
+<pre>
+&gt; f = stringio.open <span class="string">'first line\n10 20 30\n'</span>
+&gt; = f:read()
+first line
+&gt; = f:read(<span class="string">'*n'</span>,<span class="string">'*n'</span>,<span class="string">'*n'</span>)
+<span class="number">10</span> <span class="number">20</span> <span class="number">30</span>
+</pre>
+
+
+<p><code>lines</code> and <code>seek</code> are also supported.</p>
+
+<p><code>stringio.lines</code> is a useful short-cut for iterating over all the lines in a
+string.</p>
+
+<p><a href="../libraries/pl.stringio.html#create">stringio.create</a> creates a writeable file-like object. You then use <code>write</code> to
+this stream, and finally extract the builded string using <code>value</code>. This &lsquo;string
+builder&rsquo; pattern is useful for efficiently creating large strings.</p>
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/04-paths.md.html b/docs/manual/04-paths.md.html
new file mode 100644
index 0000000..125b53c
--- /dev/null
+++ b/docs/manual/04-paths.md.html
@@ -0,0 +1,330 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Working_with_Paths">Working with Paths </a></li>
+<li><a href="#File_Operations">File Operations </a></li>
+<li><a href="#Directory_Operations">Directory Operations </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><strong>Paths and Directories</strong></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Paths and Directories</h2>
+
+<p><a name="Working_with_Paths"></a></p>
+
+<h3>Working with Paths</h3>
+
+<p>Programs should not depend on quirks of your operating system. They will be
+harder to read, and need to be ported for other systems. The worst of course is
+hardcoding paths like &lsquo;c:\&rsquo; in programs, and wondering why Vista complains so
+much. But even something like <code>dir..&apos;\&apos;..file</code> is a problem, since Unix can&rsquo;t
+understand backslashes in this way. <code>dir..&apos;/&apos;..file</code> is <em>usually</em> portable, but
+it&rsquo;s best to put this all into a simple function, <a href="../libraries/pl.path.html#join">path.join</a>. If you
+consistently use <a href="../libraries/pl.path.html#join">path.join</a>, then it&rsquo;s much easier to write cross-platform code,
+since it handles the directory separator for you.</p>
+
+<p><a href="../libraries/pl.path.html#">pl.path</a> provides the same functionality as Python&rsquo;s <code>os.path</code> module (11.1).</p>
+
+<pre>
+&gt; p = <span class="string">'c:\\bonzo\\DOG.txt'</span>
+&gt; = path.normcase (p) <span class="comment">---&gt; only makes sense on Windows
+</span>c:\bonzo\dog.txt
+&gt; = path.splitext (p)
+c:\bonzo\DOG .txt
+&gt; = path.extension (p)
+.txt
+&gt; = path.basename (p)
+DOG.txt
+&gt; = path.exists(p)
+<span class="keyword">false</span>
+&gt; = path.join (<span class="string">'fred'</span>,<span class="string">'alice.txt'</span>)
+fred\alice.txt
+&gt; = path.exists <span class="string">'pretty.lua'</span>
+<span class="keyword">true</span>
+&gt; = path.getsize <span class="string">'pretty.lua'</span>
+<span class="number">2125</span>
+&gt; = path.isfile <span class="string">'pretty.lua'</span>
+<span class="keyword">true</span>
+&gt; = path.isdir <span class="string">'pretty.lua'</span>
+<span class="keyword">false</span>
+</pre>
+
+
+<p>It is very important for all programmers, not just on Unix, to only write to
+where they are allowed to write. <a href="../libraries/pl.path.html#expanduser">path.expanduser</a> will expand &lsquo;~&rsquo; (tilde) into
+the home directory. Depending on your OS, this will be a guaranteed place where
+you can create files:</p>
+
+<pre>
+&gt; = path.expanduser <span class="string">'~/mydata.txt'</span>
+<span class="string">'C:\Documents and Settings\SJDonova/mydata.txt'</span>
+
+&gt; = path.expanduser <span class="string">'~/mydata.txt'</span>
+/home/sdonovan/mydata.txt
+</pre>
+
+
+<p>Under Windows, <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.tmpname">os.tmpname</a> returns a path which leads to your drive root full of
+temporary files. (And increasingly, you do not have access to this root folder.)
+This is corrected by <a href="../libraries/pl.path.html#tmpname">path.tmpname</a>, which uses the environment variable TMP:</p>
+
+<pre>
+&gt; <span class="global">os</span>.tmpname() <span class="comment">-- not a good place to put temporary files!
+</span><span class="string">'\s25g.'</span>
+&gt; path.tmpname()
+<span class="string">'C:\DOCUME~1\SJDonova\LOCALS~1\Temp\s25g.1'</span>
+</pre>
+
+
+<p>A useful extra function is <a href="../libraries/pl.path.html#package_path">pl.path.package_path</a>, which will tell you the path
+of a particular Lua module. So on my system, <code>package_path(&apos;pl.path&apos;)</code> returns
+&lsquo;C:\Program Files\Lua\5.1\lualibs\pl\path.lua&rsquo;, and <code>package_path(&apos;ifs&apos;)</code> returns
+&lsquo;C:\Program Files\Lua\5.1\clibs\lfs.dll&rsquo;. It is implemented in terms of
+<a href="https://www.lua.org/manual/5.1/manual.html#pdf-package.searchpath">package.searchpath</a>, which is a new function in Lua 5.2 which has been
+implemented for Lua 5.1 in Penlight.</p>
+
+<p><a name="File_Operations"></a></p>
+
+<h3>File Operations</h3>
+
+<p><a href="../libraries/pl.file.html#">pl.file</a> is a new module that provides more sensible names for common file
+operations. For instance, <a href="https://www.lua.org/manual/5.1/manual.html#pdf-file:read">file.read</a> and <a href="https://www.lua.org/manual/5.1/manual.html#pdf-file:write">file.write</a> are aliases for
+<a href="../libraries/pl.utils.html#readfile">utils.readfile</a> and <a href="../libraries/pl.utils.html#writefile">utils.writefile</a>.</p>
+
+<p>Smaller files can be efficiently read and written in one operation. <a href="https://www.lua.org/manual/5.1/manual.html#pdf-file:read">file.read</a>
+is passed a filename and returns the contents as a string, if successful; if not,
+then it returns <code>nil</code> and the actual error message. There is an optional boolean
+parameter if you want the file to be read in binary mode (this makes no
+difference on Unix but remains important with Windows.)</p>
+
+<p>In previous versions of Penlight, <a href="../libraries/pl.utils.html#readfile">utils.readfile</a> would read standard input if
+the file was not specified, but this can lead to nasty bugs; use <code>io.read &apos;*a&apos;</code>
+to grab all of standard input.</p>
+
+<p>Similarly, <a href="https://www.lua.org/manual/5.1/manual.html#pdf-file:write">file.write</a> takes a filename and a string which will be written to
+that file.</p>
+
+<p>For example, this little script converts a file into upper case:</p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+<span class="global">assert</span>(#arg == <span class="number">2</span>, <span class="string">'supply two filenames'</span>)
+text = <span class="global">assert</span>(file.read(arg[<span class="number">1</span>]))
+<span class="global">assert</span>(file.write(arg[<span class="number">2</span>],text:upper()))
+</pre>
+
+
+<p>Copying files is suprisingly tricky. <a href="../libraries/pl.file.html#copy">file.copy</a> and <a href="../libraries/pl.file.html#move">file.move</a> attempt to use
+the best implementation possible. On Windows, they link to the API functions
+<code>CopyFile</code> and <code>MoveFile</code>, but only if the <code>alien</code> package is installed (this is
+true for Lua for Windows.) Otherwise, the system copy command is used. This can
+be ugly when writing Windows GUI applications, because of the dreaded flashing
+black-box problem with launching processes.</p>
+
+<p><a name="Directory_Operations"></a></p>
+
+<h3>Directory Operations</h3>
+
+<p><a href="../libraries/pl.dir.html#">pl.dir</a> provides some useful functions for working with directories. <code>fnmatch</code>
+will match a filename against a shell pattern, and <code>filter</code> will return any files
+in the supplied list which match the given pattern, which correspond to the
+functions in the Python <code>fnmatch</code> module. <code>getdirectories</code> will return all
+directories contained in a directory, and <code>getfiles</code> will return all files in a
+directory which match a shell pattern. These functions return the files as a
+table, unlike <a href="http://stevedonovan.github.io/lua-stdlibs/modules/lfs.html#dir">lfs.dir</a> which returns an iterator.)</p>
+
+<p><a href="../libraries/pl.dir.html#makepath">dir.makepath</a> can create a full path, creating subdirectories as necessary;
+<code>rmtree</code> is the Nuclear Option of file deleting functions, since it will
+recursively clear out and delete all directories found begining at a path (there
+is a similar function with this name in the Python <code>shutils</code> module.)</p>
+
+<pre>
+&gt; = dir.makepath <span class="string">'t\\temp\\bonzo'</span>
+&gt; = path.isdir <span class="string">'t\\temp\\bonzo'</span>
+<span class="keyword">true</span>
+&gt; = dir.rmtree <span class="string">'t'</span>
+</pre>
+
+
+<p><a href="../libraries/pl.dir.html#rmtree">dir.rmtree</a> depends on <a href="../libraries/pl.dir.html#walk">dir.walk</a>, which is a powerful tool for scanning a whole
+directory tree. Here is the implementation of <a href="../libraries/pl.dir.html#rmtree">dir.rmtree</a>:</p>
+
+<pre>
+<span class="comment">--- remove a whole directory tree.
+</span><span class="comment">-- @param path A directory path
+</span><span class="keyword">function</span> dir.rmtree(fullpath)
+ <span class="keyword">for</span> root,dirs,files <span class="keyword">in</span> dir.walk(fullpath) <span class="keyword">do</span>
+ <span class="keyword">for</span> i,f <span class="keyword">in</span> <span class="global">ipairs</span>(files) <span class="keyword">do</span>
+ <span class="global">os</span>.remove(path.join(root,f))
+ <span class="keyword">end</span>
+ lfs.rmdir(root)
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p><a href="../libraries/pl.dir.html#clonetree">dir.clonetree</a> clones directory trees. The first argument is a path that must
+exist, and the second path is the path to be cloned. (Note that this path cannot
+be <em>inside</em> the first path, since this leads to madness.) By default, it will
+then just recreate the directory structure. You can in addition provide a
+function, which will be applied for all files found.</p>
+
+<pre>
+<span class="comment">-- make a copy of my libs folder
+</span><span class="global">require</span> <span class="string">'pl'</span>
+p1 = <span class="string">[[d:\dev\lua\libs]]</span>
+p2 = <span class="string">[[D:\dev\lua\libs\..\tests]]</span>
+dir.clonetree(p1,p2,dir.copyfile)
+</pre>
+
+
+<p>A more sophisticated version, which only copies files which have been modified:</p>
+
+<pre>
+<span class="comment">-- p1 and p2 as before, or from arg[1] and arg[2]
+</span>dir.clonetree(p1,p2,<span class="keyword">function</span>(f1,f2)
+ <span class="keyword">local</span> res
+ <span class="keyword">local</span> t1,t2 = path.getmtime(f1),path.getmtime(f2)
+ <span class="comment">-- f2 might not exist, so be careful about t2
+</span> <span class="keyword">if</span> <span class="keyword">not</span> t2 <span class="keyword">or</span> t1 &gt; t2 <span class="keyword">then</span>
+ res = dir.copyfile(f1,f2)
+ <span class="keyword">end</span>
+ <span class="keyword">return</span> res <span class="comment">-- indicates successful operation
+</span><span class="keyword">end</span>)
+</pre>
+
+
+<p><a href="../libraries/pl.dir.html#clonetree">dir.clonetree</a> uses <a href="../libraries/pl.path.html#common_prefix">path.common_prefix</a>. With <code>p1</code> and <code>p2</code> defined above, the
+common path is &rsquo;d:\dev\lua'. So &rsquo;d:\dev\lua\libs\testfunc.lua' is copied to
+&rsquo;d:\dev\lua\test\testfunc.lua', etc.</p>
+
+<p>If you need to find the common path of list of files, then <a href="../libraries/pl.tablex.html#reduce">tablex.reduce</a> will
+do the job:</p>
+
+<pre>
+&gt; p3 = <span class="string">[[d:\dev]]</span>
+&gt; = tablex.reduce(path.common_prefix,{p1,p2,p3})
+<span class="string">'d:\dev'</span>
+</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/05-dates.md.html b/docs/manual/05-dates.md.html
new file mode 100644
index 0000000..46b78c3
--- /dev/null
+++ b/docs/manual/05-dates.md.html
@@ -0,0 +1,266 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Creating_and_Displaying_Dates">Creating and Displaying Dates </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><strong>Date and Time</strong></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Date and Time</h2>
+
+<p><a id="date"></a></p>
+
+<p><a name="Creating_and_Displaying_Dates"></a></p>
+
+<h3>Creating and Displaying Dates</h3>
+
+<p>The <a href="../classes/pl.Date.html#">Date</a> class provides a simplified way to work with <a href="http://www.lua.org/pil/22.1.html">date and
+time</a> in Lua; it leans heavily on the functions
+<a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.date">os.date</a> and <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.time">os.time</a>.</p>
+
+<p>A <a href="../classes/pl.Date.html#">Date</a> object can be constructed from a table, just like with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-os.time">os.time</a>.
+Methods are provided to get and set the various parts of the date.</p>
+
+<pre>
+&gt; d = Date {year = <span class="number">2011</span>, month = <span class="number">3</span>, day = <span class="number">2</span> }
+&gt; = d
+<span class="number">2011</span>-<span class="number">03</span>-<span class="number">02</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = d:month(),d:year(),d:day()
+<span class="number">3</span> <span class="number">2011</span> <span class="number">2</span>
+&gt; d:month(<span class="number">4</span>)
+&gt; = d
+<span class="number">2011</span>-<span class="number">04</span>-<span class="number">02</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; d:add {day=<span class="number">1</span>}
+&gt; = d
+<span class="number">2011</span>-<span class="number">04</span>-<span class="number">03</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+</pre>
+
+
+<p><code>add</code> takes a table containing one of the date table fields.</p>
+
+<pre>
+&gt; = d:weekday_name()
+Sun
+&gt; = d:last_day()
+<span class="number">2011</span>-<span class="number">04</span>-<span class="number">30</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = d:month_name(<span class="keyword">true</span>)
+April
+</pre>
+
+
+<p>There is a default conversion to text for date objects, but <a href="../classes/pl.Date.html#Date.Format">Date.Format</a> gives
+you full control of the format for both parsing and displaying dates:</p>
+
+<pre>
+&gt; iso = Date.Format <span class="string">'yyyy-mm-dd'</span>
+&gt; d = iso:parse <span class="string">'2010-04-10'</span>
+&gt; amer = Date.Format <span class="string">'mm/dd/yyyy'</span>
+&gt; = amer:<span class="global">tostring</span>(d)
+<span class="number">04</span>/<span class="number">10</span>/<span class="number">2010</span>
+</pre>
+
+
+<p>With the 0.9.7 relase, the <a href="../classes/pl.Date.html#">Date</a> constructor has become more flexible. You may
+omit any of the &lsquo;year&rsquo;, &lsquo;month&rsquo; or &lsquo;day&rsquo; fields:</p>
+
+<pre>
+&gt; = Date { year = <span class="number">2008</span> }
+<span class="number">2008</span>-<span class="number">01</span>-<span class="number">01</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = Date { month = <span class="number">3</span> }
+<span class="number">2011</span>-<span class="number">03</span>-<span class="number">01</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = Date { day = <span class="number">20</span> }
+<span class="number">2011</span>-<span class="number">10</span>-<span class="number">20</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = Date { hour = <span class="number">14</span>, min = <span class="number">30</span> }
+<span class="number">2011</span>-<span class="number">10</span>-<span class="number">13</span> <span class="number">14</span>:<span class="number">30</span>:<span class="number">00</span>
+</pre>
+
+
+<p>If &lsquo;year&rsquo; is omitted, then the current year is assumed, and likewise for &lsquo;month&rsquo;.</p>
+
+<p>To set the time on such a partial date, you can use the fact that the &lsquo;setter&rsquo;
+methods return the date object and so you can &lsquo;chain&rsquo; these methods.</p>
+
+<pre>
+&gt; d = Date { day = <span class="number">03</span> }
+&gt; = d:hour(<span class="number">18</span>):min(<span class="number">30</span>)
+<span class="number">2011</span>-<span class="number">10</span>-<span class="number">03</span> <span class="number">18</span>:<span class="number">30</span>:<span class="number">00</span>
+</pre>
+
+
+<p>Finally, <a href="../classes/pl.Date.html#">Date</a> also now accepts positional arguments:</p>
+
+<pre>
+&gt; = Date(<span class="number">2011</span>,<span class="number">10</span>,<span class="number">3</span>)
+<span class="number">2011</span>-<span class="number">10</span>-<span class="number">03</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = Date(<span class="number">2011</span>,<span class="number">10</span>,<span class="number">3</span>,<span class="number">18</span>,<span class="number">30</span>,<span class="number">23</span>)
+<span class="number">2011</span>-<span class="number">10</span>-<span class="number">03</span> <span class="number">18</span>:<span class="number">30</span>:<span class="number">23</span>
+</pre>
+
+
+<p><code>Date.format</code> has been extended. If you construct an instance without a pattern,
+then it will try to match against a set of known formats. This is useful for
+human-input dates since keeping to a strict format is not one of the strong
+points of users. It assumes that there will be a date, and then a date.</p>
+
+<pre>
+&gt; df = Date.Format()
+&gt; = df:parse <span class="string">'5.30pm'</span>
+<span class="number">2011</span>-<span class="number">10</span>-<span class="number">13</span> <span class="number">17</span>:<span class="number">30</span>:<span class="number">00</span>
+&gt; = df:parse <span class="string">'1730'</span>
+<span class="keyword">nil</span> day out of range: <span class="number">1730</span> is <span class="keyword">not</span> between <span class="number">1</span> <span class="keyword">and</span> <span class="number">31</span>
+&gt; = df:parse <span class="string">'17.30'</span>
+<span class="number">2011</span>-<span class="number">10</span>-<span class="number">13</span> <span class="number">17</span>:<span class="number">30</span>:<span class="number">00</span>
+&gt; = df:parse <span class="string">'mar'</span>
+<span class="number">2011</span>-<span class="number">03</span>-<span class="number">01</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = df:parse <span class="string">'3 March'</span>
+<span class="number">2011</span>-<span class="number">03</span>-<span class="number">03</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = df:parse <span class="string">'15 March'</span>
+<span class="number">2011</span>-<span class="number">03</span>-<span class="number">15</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = df:parse <span class="string">'15 March 2008'</span>
+<span class="number">2008</span>-<span class="number">03</span>-<span class="number">15</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+&gt; = df:parse <span class="string">'15 March 2008 1.30pm'</span>
+<span class="number">2008</span>-<span class="number">03</span>-<span class="number">15</span> <span class="number">13</span>:<span class="number">30</span>:<span class="number">00</span>
+&gt; = df:parse <span class="string">'2008-10-03 15:30:23'</span>
+<span class="number">2008</span>-<span class="number">10</span>-<span class="number">03</span> <span class="number">15</span>:<span class="number">30</span>:<span class="number">23</span>
+</pre>
+
+
+<p>ISO date format is of course a good idea if you need to deal with users from
+different countries. Here is the default behaviour for &lsquo;short&rsquo; dates:</p>
+
+<pre>
+&gt; = df:parse <span class="string">'24/02/12'</span>
+<span class="number">2012</span>-<span class="number">02</span>-<span class="number">24</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+</pre>
+
+
+<p>That&rsquo;s not what Americans expect! It&rsquo;s tricky to work out in a cross-platform way
+exactly what the expected format is, so there is an explicit flag:</p>
+
+<pre>
+&gt; df:US_order(<span class="keyword">true</span>)
+&gt; = df:parse <span class="string">'9/11/01'</span>
+<span class="number">2001</span>-<span class="number">11</span>-<span class="number">09</span> <span class="number">12</span>:<span class="number">00</span>:<span class="number">00</span>
+</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/06-data.md.html b/docs/manual/06-data.md.html
new file mode 100644
index 0000000..44bd4ed
--- /dev/null
+++ b/docs/manual/06-data.md.html
@@ -0,0 +1,1638 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Reading_Data_Files">Reading Data Files </a></li>
+<li><a href="#Reading_Unstructured_Text_Data">Reading Unstructured Text Data </a></li>
+<li><a href="#Reading_Columnar_Data">Reading Columnar Data </a></li>
+<li><a href="#Reading_Configuration_Files">Reading Configuration Files </a></li>
+<li><a href="#Lexical_Scanning">Lexical Scanning </a></li>
+<li><a href="#XML">XML </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><strong>Data</strong></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Data</h2>
+
+<p><a name="Reading_Data_Files"></a></p>
+
+<h3>Reading Data Files</h3>
+
+<p>The first thing to consider is this: do you actually need to write a custom file
+reader? And if the answer is yes, the next question is: can you write the reader
+in as clear a way as possible? Correctness, Robustness, and Speed; pick the first
+two and the third can be sorted out later, <em>if necessary</em>.</p>
+
+<p>A common sort of data file is the configuration file format commonly used on Unix
+systems. This format is often called a <em>property</em> file in the Java world.</p>
+
+<pre>
+# Read timeout <span class="keyword">in</span> seconds
+read.timeout=<span class="number">10</span>
+
+# Write timeout <span class="keyword">in</span> seconds
+write.timeout=<span class="number">10</span>
+</pre>
+
+
+<p>Here is a simple Lua implementation:</p>
+
+<pre>
+<span class="comment">-- property file parsing with Lua string patterns
+</span>props = []
+<span class="keyword">for</span> line <span class="keyword">in</span> <span class="global">io</span>.lines() <span class="keyword">do</span>
+ <span class="keyword">if</span> line:find(<span class="string">'#'</span>,<span class="number">1</span>,<span class="keyword">true</span>) ~= <span class="number">1</span> <span class="keyword">and</span> <span class="keyword">not</span> line:find(<span class="string">'^%s*$'</span>) <span class="keyword">then</span>
+ <span class="keyword">local</span> var,value = line:match(<span class="string">'([^=]+)=(.*)'</span>)
+ props[var] = value
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p>Very compact, but it suffers from a similar disease in equivalent Perl programs;
+it uses odd string patterns which are &lsquo;lexically noisy&rsquo;. Noisy code like this
+slows the casual reader down. (For an even more direct way of doing this, see the
+next section, &lsquo;Reading Configuration Files&rsquo;)</p>
+
+<p>Another implementation, using the Penlight libraries:</p>
+
+<pre>
+<span class="comment">-- property file parsing with extended string functions
+</span><span class="global">require</span> <span class="string">'pl'</span>
+stringx.import()
+props = []
+<span class="keyword">for</span> line <span class="keyword">in</span> <span class="global">io</span>.lines() <span class="keyword">do</span>
+ <span class="keyword">if</span> <span class="keyword">not</span> line:startswith(<span class="string">'#'</span>) <span class="keyword">and</span> <span class="keyword">not</span> line:isspace() <span class="keyword">then</span>
+ <span class="keyword">local</span> var,value = line:splitv(<span class="string">'='</span>)
+ props[var] = value
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p>This is more self-documenting; it is generally better to make the code express
+the <em>intention</em>, rather than having to scatter comments everywhere - comments are
+necessary, of course, but mostly to give the higher view of your intention that
+cannot be expressed in code. It is slightly slower, true, but in practice the
+speed of this script is determined by I/O, so further optimization is unnecessary.</p>
+
+<p><a name="Reading_Unstructured_Text_Data"></a></p>
+
+<h3>Reading Unstructured Text Data</h3>
+
+<p>Text data is sometimes unstructured, for example a file containing words. The
+<a href="../libraries/pl.input.html#">pl.input</a> module has a number of functions which makes processing such files
+easier. For example, a script to count the number of words in standard input
+using <code>import.words</code>:</p>
+
+<pre>
+<span class="comment">-- countwords.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+<span class="keyword">local</span> k = <span class="number">1</span>
+<span class="keyword">for</span> w <span class="keyword">in</span> input.words(<span class="global">io</span>.stdin) <span class="keyword">do</span>
+ k = k + <span class="number">1</span>
+<span class="keyword">end</span>
+<span class="global">print</span>(<span class="string">'count'</span>,k)
+</pre>
+
+
+<p>Or this script to calculate the average of a set of numbers using <a href="../libraries/pl.input.html#numbers">input.numbers</a>:</p>
+
+<pre>
+<span class="comment">-- average.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+<span class="keyword">local</span> k = <span class="number">1</span>
+<span class="keyword">local</span> sum = <span class="number">0</span>
+<span class="keyword">for</span> n <span class="keyword">in</span> input.numbers(<span class="global">io</span>.stdin) <span class="keyword">do</span>
+ sum = sum + n
+ k = k + <span class="number">1</span>
+<span class="keyword">end</span>
+<span class="global">print</span>(<span class="string">'average'</span>,sum/k)
+</pre>
+
+
+<p>These scripts can be improved further by <em>eliminating loops</em> In the last case,
+there is a perfectly good function <a href="../libraries/pl.seq.html#sum">seq.sum</a> which can already take a sequence of
+numbers and calculate these numbers for us:</p>
+
+<pre>
+<span class="comment">-- average2.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+<span class="keyword">local</span> total,n = seq.sum(input.numbers())
+<span class="global">print</span>(<span class="string">'average'</span>,total/n)
+</pre>
+
+
+<p>A further simplification here is that if <code>numbers</code> or <code>words</code> are not passed an
+argument, they will grab their input from standard input. The first script can
+be rewritten:</p>
+
+<pre>
+<span class="comment">-- countwords2.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+<span class="global">print</span>(<span class="string">'count'</span>,seq.count(input.words()))
+</pre>
+
+
+<p>A useful feature of a sequence generator like <code>numbers</code> is that it can read from
+a string source. Here is a script to calculate the sums of the numbers on each
+line in a file:</p>
+
+<pre>
+<span class="comment">-- sums.lua
+</span><span class="keyword">for</span> line <span class="keyword">in</span> <span class="global">io</span>.lines() <span class="keyword">do</span>
+ <span class="global">print</span>(seq.sum(input.numbers(line))
+<span class="keyword">end</span>
+</pre>
+
+
+<p><a name="Reading_Columnar_Data"></a></p>
+
+<h3>Reading Columnar Data</h3>
+
+<p>It is very common to find data in columnar form, either space or comma-separated,
+perhaps with an initial set of column headers. Here is a typical example:</p>
+
+<pre>
+EventID Magnitude LocationX LocationY LocationZ
+<span class="number">981124001</span> <span class="number">2.0</span> <span class="number">18988.4</span> <span class="number">10047.1</span> <span class="number">4149.7</span>
+<span class="number">981125001</span> <span class="number">0.8</span> <span class="number">19104.0</span> <span class="number">9970.4</span> <span class="number">5088.7</span>
+<span class="number">981127003</span> <span class="number">0.5</span> <span class="number">19012.5</span> <span class="number">9946.9</span> <span class="number">3831.2</span>
+...
+</pre>
+
+
+<p><a href="../libraries/pl.input.html#fields">input.fields</a> is designed to extract several columns, given some delimiter
+(default to whitespace). Here is a script to calculate the average X location of
+all the events:</p>
+
+<pre>
+<span class="comment">-- avg-x.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+<span class="global">io</span>.read() <span class="comment">-- skip the header line
+</span><span class="keyword">local</span> sum,count = seq.sum(input.fields {<span class="number">3</span>})
+<span class="global">print</span>(sum/count)
+</pre>
+
+
+<p><a href="../libraries/pl.input.html#fields">input.fields</a> is passed either a field count, or a list of column indices,
+starting at one as usual. So in this case we&rsquo;re only interested in column 3. If
+you pass it a field count, then you get every field up to that count:</p>
+
+<pre>
+<span class="keyword">for</span> id,mag,locX,locY,locZ <span class="keyword">in</span> input.fields (<span class="number">5</span>) <span class="keyword">do</span>
+....
+<span class="keyword">end</span>
+</pre>
+
+
+<p><a href="../libraries/pl.input.html#fields">input.fields</a> by default tries to convert each field to a number. It will skip
+lines which clearly don&rsquo;t match the pattern, but will abort the script if there
+are any fields which cannot be converted to numbers.</p>
+
+<p>The second parameter is a delimiter, by default spaces. &lsquo; &rsquo; is understood to mean
+&lsquo;any number of spaces&rsquo;, i.e. &lsquo;%s+&rsquo;. Any Lua string pattern can be used.</p>
+
+<p>The third parameter is a <em>data source</em>, by default standard input (defined by
+<a href="../libraries/pl.input.html#create_getter">input.create_getter</a>.) It assumes that the data source has a <code>read</code> method which
+brings in the next line, i.e. it is a &lsquo;file-like&rsquo; object. As a special case, a
+string will be split into its lines:</p>
+
+<pre>
+&gt; <span class="keyword">for</span> x,y <span class="keyword">in</span> input.fields(<span class="number">2</span>,<span class="string">' '</span>,<span class="string">'10 20\n30 40\n'</span>) <span class="keyword">do</span> <span class="global">print</span>(x,y) <span class="keyword">end</span>
+<span class="number">10</span> <span class="number">20</span>
+<span class="number">30</span> <span class="number">40</span>
+</pre>
+
+
+<p>Note the default behaviour for bad fields, which is to show the offending line
+number:</p>
+
+<pre>
+&gt; <span class="keyword">for</span> x,y <span class="keyword">in</span> input.fields(<span class="number">2</span>,<span class="string">' '</span>,<span class="string">'10 20\n30 40x\n'</span>) <span class="keyword">do</span> <span class="global">print</span>(x,y) <span class="keyword">end</span>
+<span class="number">10</span> <span class="number">20</span>
+line <span class="number">2</span>: cannot convert <span class="string">'40x'</span> to number
+</pre>
+
+
+<p>This behaviour of <a href="../libraries/pl.input.html#fields">input.fields</a> is appropriate for a script which you want to
+fail immediately with an appropriate <em>user</em> error message if conversion fails.
+The fourth optional parameter is an options table: <code>{no_fail=true}</code> means that
+conversion is attempted but if it fails it just returns the string, rather as AWK
+would operate. You are then responsible for checking the type of the returned
+field. <code>{no_convert=true}</code> switches off conversion altogether and all fields are
+returned as strings.</p>
+
+<p>Sometimes it is useful to bring a whole dataset into memory, for operations such
+as extracting columns. Penlight provides a flexible reader specifically for
+reading this kind of data, using the <a href="../libraries/pl.data.html#">data</a> module. Given a file looking like this:</p>
+
+<pre>
+x,y
+<span class="number">10</span>,<span class="number">20</span>
+<span class="number">2</span>,<span class="number">5</span>
+<span class="number">40</span>,<span class="number">50</span>
+</pre>
+
+
+<p>Then <a href="../libraries/pl.data.html#read">data.read</a> will create a table like this, with each row represented by a
+sublist:</p>
+
+<pre>
+&gt; t = data.read <span class="string">'test.txt'</span>
+&gt; pretty.dump(t)
+{{<span class="number">10</span>,<span class="number">20</span>},{<span class="number">2</span>,<span class="number">5</span>},{<span class="number">40</span>,<span class="number">50</span>},fieldnames={<span class="string">'x'</span>,<span class="string">'y'</span>},delim=<span class="string">','</span>}
+</pre>
+
+
+<p>You can now analyze this returned table using the supplied methods. For instance,
+the method <a href="../libraries/pl.data.html#Data.column_by_name">column_by_name</a> returns a table of all the values of that column.</p>
+
+<pre>
+<span class="comment">-- testdata.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+d = data.read(<span class="string">'fev.txt'</span>)
+<span class="keyword">for</span> _,name <span class="keyword">in</span> <span class="global">ipairs</span>(d.fieldnames) <span class="keyword">do</span>
+ <span class="keyword">local</span> col = d:column_by_name(name)
+ <span class="keyword">if</span> <span class="global">type</span>(col[<span class="number">1</span>]) == <span class="string">'number'</span> <span class="keyword">then</span>
+ <span class="keyword">local</span> total,n = seq.sum(col)
+ utils.printf(<span class="string">"Average for %s is %f\n"</span>,name,total/n)
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p><a href="../libraries/pl.data.html#read">data.read</a> tries to be clever when given data; by default it expects a first
+line of column names, unless any of them are numbers. It tries to deduce the
+column delimiter by looking at the first line. Sometimes it guesses wrong; these
+things can be specified explicitly. The second optional parameter is an options
+table: can override <code>delim</code> (a string pattern), <code>fieldnames</code> (a list or
+comma-separated string), specify <code>no_convert</code> (default is to convert), numfields
+(indices of columns known to be numbers, as a list) and <code>thousands_dot</code> (when the
+thousands separator in Excel CSV is &lsquo;.&rsquo;)</p>
+
+<p>A very powerful feature is a way to execute SQL-like queries on such data:</p>
+
+<pre>
+<span class="comment">-- queries on tabular data
+</span><span class="global">require</span> <span class="string">'pl'</span>
+<span class="keyword">local</span> d = data.read(<span class="string">'xyz.txt'</span>)
+<span class="keyword">local</span> q = d:<span class="global">select</span>(<span class="string">'x,y,z where x &gt; 3 and z &lt; 2 sort by y'</span>)
+<span class="keyword">for</span> x,y,z <span class="keyword">in</span> q <span class="keyword">do</span>
+ <span class="global">print</span>(x,y,z)
+<span class="keyword">end</span>
+</pre>
+
+
+<p>Please note that the format of queries is restricted to the following syntax:</p>
+
+<pre>
+FIELDLIST [ <span class="string">'where'</span> CONDITION ] [ <span class="string">'sort by'</span> FIELD [asc|desc]]
+</pre>
+
+
+<p>Any valid Lua code can appear in <code>CONDITION</code>; remember it is <em>not</em> SQL and you
+have to use <code>==</code> (this warning comes from experience.)</p>
+
+<p>For this to work, <em>field names must be Lua identifiers</em>. So <a href="../libraries/pl.data.html#read">read</a> will massage
+fieldnames so that all non-alphanumeric chars are replaced with underscores.
+However, the <code>original_fieldnames</code> field always contains the original un-massaged
+fieldnames.</p>
+
+<p><a href="../libraries/pl.data.html#read">read</a> can handle standard CSV files fine, although doesn&rsquo;t try to be a
+full-blown CSV parser. With the <code>csv=true</code> option, it&rsquo;s possible to have
+double-quoted fields, which may contain commas; then trailing commas become
+significant as well.</p>
+
+<p>Spreadsheet programs are not always the best tool to
+process such data, strange as this might seem to some people. This is a toy CSV
+file; to appreciate the problem, imagine thousands of rows and dozens of columns
+like this:</p>
+
+<pre>
+Department Name,Employee ID,Project,Hours Booked
+sales,<span class="number">1231</span>,overhead,<span class="number">4</span>
+sales,<span class="number">1255</span>,overhead,<span class="number">3</span>
+engineering,<span class="number">1501</span>,development,<span class="number">5</span>
+engineering,<span class="number">1501</span>,maintenance,<span class="number">3</span>
+engineering,<span class="number">1433</span>,maintenance,<span class="number">10</span>
+</pre>
+
+
+<p>The task is to reduce the dataset to a relevant set of rows and columns, perhaps
+do some processing on row data, and write the result out to a new CSV file. The
+<a href="../libraries/pl.data.html#Data.write_row">write_row</a> method uses the delimiter to write the row to a file;
+<code>Data.select_row</code> is like <code>Data.select</code>, except it iterates over <em>rows</em>, not
+fields; this is necessary if we are dealing with a lot of columns!</p>
+
+<pre>
+names = {[<span class="number">1501</span>]=<span class="string">'don'</span>,[<span class="number">1433</span>]=<span class="string">'dilbert'</span>}
+keepcols = {<span class="string">'Employee_ID'</span>,<span class="string">'Hours_Booked'</span>}
+t:write_row (outf,{<span class="string">'Employee'</span>,<span class="string">'Hours_Booked'</span>})
+q = t:select_row {
+ fields=keepcols,
+ where=<span class="keyword">function</span>(row) <span class="keyword">return</span> row[<span class="number">1</span>]==<span class="string">'engineering'</span> <span class="keyword">end</span>
+}
+<span class="keyword">for</span> row <span class="keyword">in</span> q <span class="keyword">do</span>
+ row[<span class="number">1</span>] = names[row[<span class="number">1</span>]]
+ t:write_row(outf,row)
+<span class="keyword">end</span>
+</pre>
+
+
+<p><code>Data.select_row</code> and <code>Data.select</code> can be passed a table specifying the query; a
+list of field names, a function defining the condition and an optional parameter
+<code>sort_by</code>. It isn&rsquo;t really necessary here, but if we had a more complicated row
+condition (such as belonging to a specified set) then it is not generally
+possible to express such a condition as a query string, without resorting to
+hackery such as global variables.</p>
+
+<p>With 1.0.3, you can specify explicit conversion functions for selected columns.
+For instance, this is a log file with a Unix date stamp:</p>
+
+<pre>
+Time Message
+<span class="number">1266840760</span> +# EE7C0600006F0D00C00F06010302054000000308010A00002B00407B00
+<span class="number">1266840760</span> closure data <span class="number">0.000000</span> <span class="number">1972</span> <span class="number">1972</span> <span class="number">0</span>
+<span class="number">1266840760</span> ++ <span class="number">1266840760</span> EE <span class="number">1</span>
+<span class="number">1266840760</span> +# EE7C0600006F0D00C00F06010302054000000408020A00002B00407B00
+<span class="number">1266840764</span> closure data <span class="number">0.000000</span> <span class="number">1972</span> <span class="number">1972</span> <span class="number">0</span>
+</pre>
+
+
+<p>We would like the first column as an actual date object, so the <code>convert</code>
+field sets an explicit conversion for column 1. (Note that we have to explicitly
+convert the string to a number first.)</p>
+
+<pre>
+Date = <span class="global">require</span> <span class="string">'pl.Date'</span>
+
+<span class="keyword">function</span> date_convert (ds)
+ <span class="keyword">return</span> Date(<span class="global">tonumber</span>(ds))
+<span class="keyword">end</span>
+
+d = data.read(f,{convert={[<span class="number">1</span>]=date_convert},last_field_collect=<span class="keyword">true</span>})
+</pre>
+
+
+<p>This gives us a two-column dataset, where the first column contains <a href="../classes/pl.Date.html#">Date</a> objects
+and the second column contains the rest of the line. Queries can then easily
+pick out events on a day of the week:</p>
+
+<pre>
+q = d:<span class="global">select</span> <span class="string">"Time,Message where Time:weekday_name()=='Sun'"</span>
+</pre>
+
+
+<p>Data does not have to come from files, nor does it necessarily come from the lab
+or the accounts department. On Linux, <code>ps aux</code> gives you a full listing of all
+processes running on your machine. It is straightforward to feed the output of
+this command into <a href="../libraries/pl.data.html#read">data.read</a> and perform useful queries on it. Notice that
+non-identifier characters like &lsquo;%&rsquo; get converted into underscores:</p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+f = <span class="global">io</span>.popen <span class="string">'ps aux'</span>
+s = data.read (f,{last_field_collect=<span class="keyword">true</span>})
+f:close()
+<span class="global">print</span>(s.fieldnames)
+<span class="global">print</span>(s:column_by_name <span class="string">'USER'</span>)
+qs = <span class="string">'COMMAND,_MEM where _MEM &gt; 5 and USER=="steve"'</span>
+<span class="keyword">for</span> name,mem <span class="keyword">in</span> s:<span class="global">select</span>(qs) <span class="keyword">do</span>
+ <span class="global">print</span>(mem,name)
+<span class="keyword">end</span>
+</pre>
+
+
+<p>I&rsquo;ve always been an admirer of the AWK programming language; with <a href="../libraries/pl.data.html#filter">filter</a> you
+can get Lua programs which are just as compact:</p>
+
+<pre>
+<span class="comment">-- printxy.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+data.filter <span class="string">'x,y where x &gt; 3'</span>
+</pre>
+
+
+<p>It is common enough to have data files without headers of field names.
+<a href="../libraries/pl.data.html#read">data.read</a> makes a special exception for such files if all fields are numeric.
+Since there are no column names to use in query expressions, you can use AWK-like
+column indexes, e.g. &lsquo;$1,$2 where $1 > 3&rsquo;. I have a little executable script on
+my system called <code>lf</code> which looks like this:</p>
+
+<pre>
+#!/usr/bin/env lua
+<span class="global">require</span> <span class="string">'pl.data'</span>.filter(arg[<span class="number">1</span>])
+</pre>
+
+
+<p>And it can be used generally as a filter command to extract columns from data.
+(The column specifications may be expressions or even constants.)</p>
+
+<pre>
+$ lf <span class="string">'$1,$5/10'</span> &lt; test.dat
+</pre>
+
+
+<p>(As with AWK, please note the single-quotes used in this command; this prevents
+the shell trying to expand the column indexes. If you are on Windows, then you
+must quote the expression in double-quotes so
+it is passed as one argument to your batch file.)</p>
+
+<p>As a tutorial resource, have a look at <a href="../examples/test-data.lua.html#">test-data.lua</a> in the PL tests directory
+for other examples of use, plus comments.</p>
+
+<p>The data returned by <a href="../libraries/pl.data.html#read">read</a> or constructed by <code>Data.copy_select</code> from a query is
+basically just an array of rows: <code>{{1,2},{3,4}}</code>. So you may use <a href="../libraries/pl.data.html#read">read</a> to pull
+in any array-like dataset, and process with any function that expects such a
+implementation. In particular, the functions in <a href="../libraries/pl.array2d.html#">array2d</a> will work fine with
+this data. In fact, these functions are available as methods; e.g.
+<a href="../libraries/pl.array2d.html#flatten">array2d.flatten</a> can be called directly like so to give us a one-dimensional list:</p>
+
+<pre>
+v = data.read(<span class="string">'dat.txt'</span>):flatten()
+</pre>
+
+
+<p>The data is also in exactly the right shape to be treated as matrices by
+<a href="http://lua-users.org/wiki/LuaMatrix">LuaMatrix</a>:</p>
+
+<pre>
+&gt; matrix = <span class="global">require</span> <span class="string">'matrix'</span>
+&gt; m = matrix(data.read <span class="string">'mat.txt'</span>)
+&gt; = m
+<span class="number">1</span> <span class="number">0.2</span> <span class="number">0.3</span>
+<span class="number">0.2</span> <span class="number">1</span> <span class="number">0.1</span>
+<span class="number">0.1</span> <span class="number">0.2</span> <span class="number">1</span>
+&gt; = m^<span class="number">2</span> <span class="comment">-- same as m*m
+</span><span class="number">1.07</span> <span class="number">0.46</span> <span class="number">0.62</span>
+<span class="number">0.41</span> <span class="number">1.06</span> <span class="number">0.26</span>
+<span class="number">0.24</span> <span class="number">0.42</span> <span class="number">1.05</span>
+</pre>
+
+
+<p><a href="../libraries/pl.data.html#write">write</a> will write matrices back to files for you.</p>
+
+<p>Finally, for the curious, the global variable <code>_DEBUG</code> can be used to print out
+the actual iterator function which a query generates and dynamically compiles. By
+using code generation, we can get pretty much optimal performance out of
+arbitrary queries.</p>
+
+<pre>
+&gt; lua -lpl -e <span class="string">"_DEBUG=true"</span> -e <span class="string">"data.filter 'x,y where x &gt; 4 sort by x'"</span> &lt; test.txt
+<span class="keyword">return</span> <span class="keyword">function</span> (t)
+ <span class="keyword">local</span> i = <span class="number">0</span>
+ <span class="keyword">local</span> v
+ <span class="keyword">local</span> ls = {}
+ <span class="keyword">for</span> i,v <span class="keyword">in</span> <span class="global">ipairs</span>(t) <span class="keyword">do</span>
+ <span class="keyword">if</span> v[<span class="number">1</span>] &gt; <span class="number">4</span> <span class="keyword">then</span>
+ ls[#ls+<span class="number">1</span>] = v
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="global">table</span>.sort(ls,<span class="keyword">function</span>(v1,v2)
+ <span class="keyword">return</span> v1[<span class="number">1</span>] &lt; v2[<span class="number">1</span>]
+ <span class="keyword">end</span>)
+ <span class="keyword">local</span> n = #ls
+ <span class="keyword">return</span> <span class="keyword">function</span>()
+ i = i + <span class="number">1</span>
+ v = ls[i]
+ <span class="keyword">if</span> i &gt; n <span class="keyword">then</span> <span class="keyword">return</span> <span class="keyword">end</span>
+ <span class="keyword">return</span> v[<span class="number">1</span>],v[<span class="number">2</span>]
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+<span class="number">10</span>,<span class="number">20</span>
+<span class="number">40</span>,<span class="number">50</span>
+</pre>
+
+
+<p><a name="Reading_Configuration_Files"></a></p>
+
+<h3>Reading Configuration Files</h3>
+
+<p>The <a href="../libraries/pl.config.html#">config</a> module provides a simple way to convert several kinds of
+configuration files into a Lua table. Consider the simple example:</p>
+
+<pre>
+# test.config
+# Read timeout <span class="keyword">in</span> seconds
+read.timeout=<span class="number">10</span>
+
+# Write timeout <span class="keyword">in</span> seconds
+write.timeout=<span class="number">5</span>
+
+#acceptable ports
+ports = <span class="number">1002</span>,<span class="number">1003</span>,<span class="number">1004</span>
+</pre>
+
+
+<p>This can be easily brought in using <a href="../libraries/pl.config.html#read">config.read</a> and the result shown using
+<a href="../libraries/pl.pretty.html#write">pretty.write</a>:</p>
+
+<pre>
+<span class="comment">-- readconfig.lua
+</span><span class="keyword">local</span> config = <span class="global">require</span> <span class="string">'pl.config'</span>
+<span class="keyword">local</span> pretty= <span class="global">require</span> <span class="string">'pl.pretty'</span>
+
+<span class="keyword">local</span> t = config.read(arg[<span class="number">1</span>])
+<span class="global">print</span>(pretty.write(t))
+</pre>
+
+
+<p>and the output of <code>lua readconfig.lua test.config</code> is:</p>
+
+<pre>
+{
+ ports = {
+ <span class="number">1002</span>,
+ <span class="number">1003</span>,
+ <span class="number">1004</span>
+ },
+ write_timeout = <span class="number">5</span>,
+ read_timeout = <span class="number">10</span>
+}
+</pre>
+
+
+<p>That is, <a href="../libraries/pl.config.html#read">config.read</a> will bring in all key/value pairs, ignore # comments, and
+ensure that the key names are proper Lua identifiers by replacing non-identifier
+characters with &lsquo;_&rsquo;. If the values are numbers, then they will be converted. (So
+the value of <code>t.write_timeout</code> is the number 5). In addition, any values which
+are separated by commas will be converted likewise into an array.</p>
+
+<p>Any line can be continued with a backslash. So this will all be considered one
+line:</p>
+
+<pre>
+names=one,two,three, \
+four,five,six,seven, \
+eight,nine,ten
+</pre>
+
+
+<p>Windows-style INI files are also supported. The section structure of INI files
+translates naturally to nested tables in Lua:</p>
+
+<pre>
+; test.ini
+[timeouts]
+read=<span class="number">10</span> ; Read timeout <span class="keyword">in</span> seconds
+write=<span class="number">5</span> ; Write timeout <span class="keyword">in</span> seconds
+[portinfo]
+ports = <span class="number">1002</span>,<span class="number">1003</span>,<span class="number">1004</span>
+</pre>
+
+
+<p> The output is:</p>
+
+<pre>
+{
+ portinfo = {
+ ports = {
+ <span class="number">1002</span>,
+ <span class="number">1003</span>,
+ <span class="number">1004</span>
+ }
+ },
+ timeouts = {
+ write = <span class="number">5</span>,
+ read = <span class="number">10</span>
+ }
+}
+</pre>
+
+
+<p>You can now refer to the write timeout as <code>t.timeouts.write</code>.</p>
+
+<p>As a final example of the flexibility of <a href="../libraries/pl.config.html#read">config.read</a>, if passed this simple
+comma-delimited file</p>
+
+<pre>
+one,two,three
+<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>
+<span class="number">40</span>,<span class="number">50</span>,<span class="number">60</span>
+<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>
+</pre>
+
+
+<p>it will produce the following table:</p>
+
+<pre>
+{
+ { <span class="string">"one"</span>, <span class="string">"two"</span>, <span class="string">"three"</span> },
+ { <span class="number">10</span>, <span class="number">20</span>, <span class="number">30</span> },
+ { <span class="number">40</span>, <span class="number">50</span>, <span class="number">60</span> },
+ { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span> }
+}
+</pre>
+
+
+<p><a href="../libraries/pl.config.html#read">config.read</a> isn&rsquo;t designed to read all CSV files in general, but intended to
+support some Unix configuration files not structured as key-value pairs, such as
+&lsquo;/etc/passwd&rsquo;.</p>
+
+<p>This function is intended to be a Swiss Army Knife of configuration readers, but
+it does have to make assumptions, and you may not like them. So there is an
+optional extra parameter which allows some control, which is table that may have
+the following fields:</p>
+
+<pre>
+{
+ variablilize = <span class="keyword">true</span>,
+ convert_numbers = <span class="global">tonumber</span>,
+ trim_space = <span class="keyword">true</span>,
+ list_delim = <span class="string">','</span>,
+ trim_quotes = <span class="keyword">true</span>,
+ ignore_assign = <span class="keyword">false</span>,
+ keysep = <span class="string">'='</span>,
+ smart = <span class="keyword">false</span>,
+}
+</pre>
+
+
+<p><code>variablilize</code> is the option that converted <code>write.timeout</code> in the first example
+to the valid Lua identifier <code>write_timeout</code>. If <code>convert_numbers</code> is true, then
+an attempt is made to convert any string that starts like a number. You can
+specify your own function (say one that will convert a string like &lsquo;5224 kb&rsquo; into
+a number.)</p>
+
+<p><code>trim_space</code> ensures that there is no starting or trailing whitespace with
+values, and <code>list_delim</code> is the character that will be used to decide whether to
+split a value up into a list (it may be a Lua string pattern such as &lsquo;%s+&rsquo;.)</p>
+
+<p>For instance, the password file in Unix is colon-delimited:</p>
+
+<pre>
+t = config.read(<span class="string">'/etc/passwd'</span>,{list_delim=<span class="string">':'</span>})
+</pre>
+
+
+<p>This produces the following output on my system (only last two lines shown):</p>
+
+<pre>
+{
+ ...
+ {
+ <span class="string">"user"</span>,
+ <span class="string">"x"</span>,
+ <span class="string">"1000"</span>,
+ <span class="string">"1000"</span>,
+ <span class="string">"user,,,"</span>,
+ <span class="string">"/home/user"</span>,
+ <span class="string">"/bin/bash"</span>
+ },
+ {
+ <span class="string">"sdonovan"</span>,
+ <span class="string">"x"</span>,
+ <span class="string">"1001"</span>,
+ <span class="string">"1001"</span>,
+ <span class="string">"steve donovan,28,,"</span>,
+ <span class="string">"/home/sdonovan"</span>,
+ <span class="string">"/bin/bash"</span>
+ }
+}
+</pre>
+
+
+<p>You can get this into a more sensible format, where the usernames are the keys,
+with this (the <a href="../libraries/pl.tablex.html#pairmap">tablex.pairmap</a> function must return value, key!)</p>
+
+<pre>
+t = tablex.pairmap(<span class="keyword">function</span>(k,v) <span class="keyword">return</span> v,v[<span class="number">1</span>] <span class="keyword">end</span>,t)
+</pre>
+
+
+<p>and you get:</p>
+
+<pre>
+{ ...
+ sdonovan = {
+ <span class="string">"sdonovan"</span>,
+ <span class="string">"x"</span>,
+ <span class="string">"1001"</span>,
+ <span class="string">"1001"</span>,
+ <span class="string">"steve donovan,28,,"</span>,
+ <span class="string">"/home/sdonovan"</span>,
+ <span class="string">"/bin/bash"</span>
+ }
+...
+}
+</pre>
+
+
+<p>Many common Unix configuration files can be read by tweaking these parameters.
+For <code>/etc/fstab</code>, the options <code>{list_delim=&apos;%s+&apos;,ignore_assign=true}</code> will
+correctly separate the columns. It&rsquo;s common to find &lsquo;KEY VALUE&rsquo; assignments in
+files such as <code>/etc/ssh/ssh_config</code>; the options <code>{keysep=&apos; &apos;}</code> make
+<a href="../libraries/pl.config.html#read">config.read</a> return a table where each KEY has a value VALUE.</p>
+
+<p>Files in the Linux <code>procfs</code> usually use &lsquo;:` as the field delimiter:</p>
+
+<pre>
+&gt; t = config.read(<span class="string">'/proc/meminfo'</span>,{keysep=<span class="string">':'</span>})
+&gt; = t.MemFree
+<span class="number">220140</span> kB
+</pre>
+
+
+<p>That result is a string, since <a href="https://www.lua.org/manual/5.1/manual.html#pdf-tonumber">tonumber</a> doesn&rsquo;t like it, but defining the
+<code>convert_numbers</code> option as <code>function(s) return tonumber((s:gsub(' kB$','')))
+end</code> will get the memory figures as actual numbers in the result. (The extra
+parentheses are necessary so that <a href="https://www.lua.org/manual/5.1/manual.html#pdf-tonumber">tonumber</a> only gets the first result from
+<code>gsub</code>). From `tests/test-config.lua':</p>
+
+<pre>
+testconfig(<span class="string">[[
+MemTotal: 1024748 kB
+MemFree: 220292 kB
+]]</span>,
+{ MemTotal = <span class="number">1024748</span>, MemFree = <span class="number">220292</span> },
+{
+ keysep = <span class="string">':'</span>,
+ convert_numbers = <span class="keyword">function</span>(s)
+ s = s:gsub(<span class="string">' kB$'</span>,<span class="string">''</span>)
+ <span class="keyword">return</span> <span class="global">tonumber</span>(s)
+ <span class="keyword">end</span>
+ }
+)
+</pre>
+
+
+<p>The <code>smart</code> option lets <a href="../libraries/pl.config.html#read">config.read</a> make a reasonable guess for you; there
+are examples in <code>tests/test-config.lua</code>, but basically these common file
+formats (and those following the same pattern) can be processed directly in
+smart mode: &lsquo;etc/fstab&rsquo;, &lsquo;/proc/XXXX/status&rsquo;, &lsquo;ssh_config&rsquo; and &lsquo;pdatedb.conf&rsquo;.</p>
+
+<p>Please note that <a href="../libraries/pl.config.html#read">config.read</a> can be passed a <em>file-like object</em>; if it&rsquo;s not a
+string and supports the <a href="../libraries/pl.data.html#read">read</a> method, then that will be used. For instance, to
+read a configuration from a string, use <a href="../libraries/pl.stringio.html#open">stringio.open</a>.</p>
+
+<p><a id="lexer"/></p>
+
+<p><a name="Lexical_Scanning"></a></p>
+
+<h3>Lexical Scanning</h3>
+
+<p>Although Lua&rsquo;s string pattern matching is very powerful, there are times when
+something more powerful is needed. <a href="../libraries/pl.lexer.html#scan">pl.lexer.scan</a> provides lexical scanners
+which <em>tokenize</em> a string, classifying tokens into numbers, strings, etc.</p>
+
+<pre>
+&gt; lua -lpl
+Lua <span class="number">5.1</span>.<span class="number">4</span> Copyright (C) <span class="number">1994</span>-<span class="number">2008</span> Lua.org, PUC-Rio
+&gt; tok = lexer.scan <span class="string">'alpha = sin(1.5)'</span>
+&gt; = tok()
+iden alpha
+&gt; = tok()
+= =
+&gt; = tok()
+iden sin
+&gt; = tok()
+( (
+&gt; = tok()
+number <span class="number">1.5</span>
+&gt; = tok()
+) )
+&gt; = tok()
+(<span class="keyword">nil</span>)
+</pre>
+
+
+<p>The scanner is a function, which is repeatedly called and returns the <em>type</em> and
+<em>value</em> of the token. Recognized basic types are &lsquo;iden&rsquo;,&lsquo;string&rsquo;,&lsquo;number&rsquo;, and
+&lsquo;space&rsquo;. and everything else is represented by itself. Note that by default the
+scanner will skip any &lsquo;space&rsquo; tokens.</p>
+
+<p>&lsquo;comment&rsquo; and &lsquo;keyword&rsquo; aren&rsquo;t applicable to the plain scanner, which is not
+language-specific, but a scanner which understands Lua is available. It
+recognizes the Lua keywords, and understands both short and long comments and
+strings.</p>
+
+<pre>
+&gt; <span class="keyword">for</span> t,v <span class="keyword">in</span> lexer.lua <span class="string">'for i=1,n do'</span> <span class="keyword">do</span> <span class="global">print</span>(t,v) <span class="keyword">end</span>
+keyword <span class="keyword">for</span>
+iden i
+= =
+number <span class="number">1</span>
+, ,
+iden n
+keyword <span class="keyword">do</span>
+</pre>
+
+
+<p>A lexical scanner is useful where you have highly-structured data which is not
+nicely delimited by newlines. For example, here is a snippet of a in-house file
+format which it was my task to maintain:</p>
+
+<pre>
+points
+</pre>
+
+
+<p>(818344.1,-20389.7,-0.1),(818337.9,-20389.3,-0.1),(818332.5,-20387.8,-0.1)</p>
+
+<pre>
+,(<span class="number">818327.4</span>,-<span class="number">20388</span>,-<span class="number">0.1</span>),(<span class="number">818322</span>,-<span class="number">20387.7</span>,-<span class="number">0.1</span>),(<span class="number">818316.3</span>,-<span class="number">20388.6</span>,-<span class="number">0.1</span>)
+,(<span class="number">818309.7</span>,-<span class="number">20389.4</span>,-<span class="number">0.1</span>),(<span class="number">818303.5</span>,-<span class="number">20390.6</span>,-<span class="number">0.1</span>),(<span class="number">818295.8</span>,-<span class="number">20388.3</span>,-<span class="number">0.1</span>)
+,(<span class="number">818290.5</span>,-<span class="number">20386.9</span>,-<span class="number">0.1</span>),(<span class="number">818285.2</span>,-<span class="number">20386.1</span>,-<span class="number">0.1</span>),(<span class="number">818279.3</span>,-<span class="number">20383.6</span>,-<span class="number">0.1</span>)
+,(<span class="number">818274</span>,-<span class="number">20381.2</span>,-<span class="number">0.1</span>),(<span class="number">818274</span>,-<span class="number">20380.7</span>,-<span class="number">0.1</span>);
+</pre>
+
+
+<p>Here is code to extract the points using <a href="../libraries/pl.lexer.html#">pl.lexer</a>:</p>
+
+<pre>
+<span class="comment">-- assume 's' contains the text above...
+</span><span class="keyword">local</span> lexer = <span class="global">require</span> <span class="string">'pl.lexer'</span>
+<span class="keyword">local</span> expecting = lexer.expecting
+<span class="keyword">local</span> append = <span class="global">table</span>.insert
+
+<span class="keyword">local</span> tok = lexer.scan(s)
+
+<span class="keyword">local</span> points = {}
+<span class="keyword">local</span> t,v = tok() <span class="comment">-- should be 'iden','points'
+</span>
+<span class="keyword">while</span> t ~= <span class="string">';'</span> <span class="keyword">do</span>
+ c = {}
+ expecting(tok,<span class="string">'('</span>)
+ c.x = expecting(tok,<span class="string">'number'</span>)
+ expecting(tok,<span class="string">','</span>)
+ c.y = expecting(tok,<span class="string">'number'</span>)
+ expecting(tok,<span class="string">','</span>)
+ c.z = expecting(tok,<span class="string">'number'</span>)
+ expecting(tok,<span class="string">')'</span>)
+ t,v = tok() <span class="comment">-- either ',' or ';'
+</span> append(points,c)
+<span class="keyword">end</span>
+</pre>
+
+
+<p>The <code>expecting</code> function grabs the next token and if the type doesn&rsquo;t match, it
+throws an error. (<a href="../libraries/pl.lexer.html#">pl.lexer</a>, unlike other PL libraries, raises errors if
+something goes wrong, so you should wrap your code in <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pcall">pcall</a> to catch the error
+gracefully.)</p>
+
+<p>The scanners all have a second optional argument, which is a table which controls
+whether you want to exclude spaces and/or comments. The default for <a href="../libraries/pl.lexer.html#lua">lexer.lua</a>
+is <code>{space=true,comments=true}</code>. There is a third optional argument which
+determines how string and number tokens are to be processsed.</p>
+
+<p>The ultimate highly-structured data is of course, program source. Here is a
+snippet from &lsquo;text-lexer.lua&rsquo;:</p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+
+lines = <span class="string">[[
+for k,v in pairs(t) do
+ if type(k) == 'number' then
+ print(v) -- array-like case
+ else
+ print(k,v)
+ end
+end
+]]</span>
+
+ls = List()
+<span class="keyword">for</span> tp,val <span class="keyword">in</span> lexer.lua(lines,{space=<span class="keyword">true</span>,comments=<span class="keyword">true</span>}) <span class="keyword">do</span>
+ <span class="global">assert</span>(tp ~= <span class="string">'space'</span> <span class="keyword">and</span> tp ~= <span class="string">'comment'</span>)
+ <span class="keyword">if</span> tp == <span class="string">'keyword'</span> <span class="keyword">then</span> ls:append(val) <span class="keyword">end</span>
+<span class="keyword">end</span>
+test.asserteq(ls,List{<span class="string">'for'</span>,<span class="string">'in'</span>,<span class="string">'do'</span>,<span class="string">'if'</span>,<span class="string">'then'</span>,<span class="string">'else'</span>,<span class="string">'end'</span>,<span class="string">'end'</span>})
+</pre>
+
+
+<p>Here is a useful little utility that identifies all common global variables found
+in a lua module (ignoring those declared locally for the moment):</p>
+
+<pre>
+<span class="comment">-- testglobal.lua
+</span><span class="global">require</span> <span class="string">'pl'</span>
+
+<span class="keyword">local</span> txt,err = utils.readfile(arg[<span class="number">1</span>])
+<span class="keyword">if</span> <span class="keyword">not</span> txt <span class="keyword">then</span> <span class="keyword">return</span> <span class="global">print</span>(err) <span class="keyword">end</span>
+
+<span class="keyword">local</span> globals = List()
+<span class="keyword">for</span> t,v <span class="keyword">in</span> lexer.lua(txt) <span class="keyword">do</span>
+ <span class="keyword">if</span> t == <span class="string">'iden'</span> <span class="keyword">and</span> _G[v] <span class="keyword">then</span>
+ globals:append(v)
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+pretty.dump(seq.count_map(globals))
+</pre>
+
+
+<p>Rather then dumping the whole list, with its duplicates, we pass it through
+<a href="../libraries/pl.seq.html#count_map">seq.count_map</a> which turns the list into a table where the keys are the values,
+and the associated values are the number of times those values occur in the
+sequence. Typical output looks like this:</p>
+
+<pre>
+{
+ <span class="global">type</span> = <span class="number">2</span>,
+ <span class="global">pairs</span> = <span class="number">2</span>,
+ <span class="global">table</span> = <span class="number">2</span>,
+ <span class="global">print</span> = <span class="number">3</span>,
+ <span class="global">tostring</span> = <span class="number">2</span>,
+ <span class="global">require</span> = <span class="number">1</span>,
+ <span class="global">ipairs</span> = <span class="number">4</span>
+}
+</pre>
+
+
+<p>You could further pass this through <a href="../libraries/pl.tablex.html#keys">tablex.keys</a> to get a unique list of
+symbols. This can be useful when writing &lsquo;strict&rsquo; Lua modules, where all global
+symbols must be defined as locals at the top of the file.</p>
+
+<p>For a more detailed use of <a href="../libraries/pl.lexer.html#scan">lexer.scan</a>, please look at <a href="../examples/testxml.lua.html#">testxml.lua</a> in the
+examples directory.</p>
+
+<p><a name="XML"></a></p>
+
+<h3>XML</h3>
+
+<p>New in the 0.9.7 release is some support for XML. This is a large topic, and
+Penlight does not provide a full XML stack, which is properly the task of a more
+specialized library.</p>
+
+<h4>Parsing and Pretty-Printing</h4>
+
+<p>The semi-standard XML parser in the Lua universe is <a href="http://matthewwild.co.uk/projects/luaexpat/">lua-expat</a>.
+In particular,
+it has a function called <code>lxp.lom.parse</code> which will parse XML into the Lua Object
+Model (LOM) format. However, it does not provide a way to convert this data back
+into XML text. <a href="../libraries/pl.xml.html#parse">xml.parse</a> will use this function, <em>if</em> <code>lua-expat</code> is
+available, and otherwise switches back to a pure Lua parser originally written by
+Roberto Ierusalimschy.</p>
+
+<p>The resulting document object knows how to render itself as a string, which is
+useful for debugging:</p>
+
+<pre>
+&gt; d = xml.parse <span class="string">"&lt;nodes&gt;&lt;node id='1'&gt;alice&lt;/node&gt;&lt;/nodes&gt;"</span>
+&gt; = d
+&lt;nodes&gt;&lt;node id=<span class="string">'1'</span>&gt;alice&lt;/node&gt;&lt;/nodes&gt;
+&gt; pretty.dump (d)
+{
+ {
+ <span class="string">"alice"</span>,
+ attr = {
+ <span class="string">"id"</span>,
+ id = <span class="string">"1"</span>
+ },
+ tag = <span class="string">"node"</span>
+ },
+ attr = {
+ },
+ tag = <span class="string">"nodes"</span>
+}
+</pre>
+
+
+<p>Looking at the actual shape of the data reveals the structure of LOM:</p>
+
+<ul>
+<li>every element has a <code>tag</code> field with its name</li>
+<li>plus a <code>attr</code> field which is a table containing the attributes as fields, and
+also as an array. It is always present.</li>
+<li>the children of the element are the array part of the element, so <code>d[1]</code> is
+the first child of <code>d</code>, etc.</li>
+</ul>
+
+
+<p>It could be argued that having attributes also as the array part of <code>attr</code> is not
+essential (you cannot depend on attribute order in XML) but that&rsquo;s how
+it goes with this standard.</p>
+
+<p><code>lua-expat</code> is another <em>soft dependency</em> of Penlight; generally, the fallback
+parser is good enough for straightforward XML as is commonly found in
+configuration files, etc. <code>doc.basic_parse</code> is not intended to be a proper
+conforming parser (it&rsquo;s only sixty lines) but it handles simple kinds of
+documents that do not have comments or DTD directives. It is intelligent enough
+to ignore the <code>&lt;?xml</code> directive and that is about it.</p>
+
+<p>You can get pretty-printing by explicitly calling <a href="../libraries/pl.xml.html#tostring">xml.tostring</a> and passing it
+the initial indent and the per-element indent:</p>
+
+<pre>
+&gt; = xml.<span class="global">tostring</span>(d,<span class="string">''</span>,<span class="string">' '</span>)
+
+&lt;nodes&gt;
+ &lt;node id=<span class="string">'1'</span>&gt;alice&lt;/node&gt;
+&lt;/nodes&gt;
+</pre>
+
+
+<p>There is a fourth argument which is the <em>attribute indent</em>:</p>
+
+<pre>
+&gt; a = xml.parse <span class="string">"&lt;frodo name='baggins' age='50' type='hobbit'/&gt;"</span>
+&gt; = xml.<span class="global">tostring</span>(a,<span class="string">''</span>,<span class="string">' '</span>,<span class="string">' '</span>)
+
+&lt;frodo
+ <span class="global">type</span>=<span class="string">'hobbit'</span>
+ name=<span class="string">'baggins'</span>
+ age=<span class="string">'50'</span>
+/&gt;
+</pre>
+
+
+<h4>Parsing and Working with Configuration Files</h4>
+
+<p>It&rsquo;s common to find configurations expressed with XML these days. It&rsquo;s
+straightforward to &lsquo;walk&rsquo; the <a href="http://matthewwild.co.uk/projects/luaexpat/lom.html">LOM</a>
+data and extract the data in the form you want:</p>
+
+<pre>
+<span class="global">require</span> <span class="string">'pl'</span>
+
+<span class="keyword">local</span> config = <span class="string">[[
+&lt;config&gt;
+ &lt;alpha&gt;1.3&lt;/alpha&gt;
+ &lt;beta&gt;10&lt;/beta&gt;
+ &lt;name&gt;bozo&lt;/name&gt;
+&lt;/config&gt;
+]]</span>
+<span class="keyword">local</span> d,err = xml.parse(config)
+
+<span class="keyword">local</span> t = {}
+<span class="keyword">for</span> item <span class="keyword">in</span> d:childtags() <span class="keyword">do</span>
+ t[item.tag] = item[<span class="number">1</span>]
+<span class="keyword">end</span>
+
+pretty.dump(t)
+<span class="comment">---&gt;
+</span>{
+ beta = <span class="string">"10"</span>,
+ alpha = <span class="string">"1.3"</span>,
+ name = <span class="string">"bozo"</span>
+}
+</pre>
+
+
+<p>The only gotcha is that here we must use the <code>Doc:childtags</code> method, which will
+skip over any text elements.</p>
+
+<p>A more involved example is this excerpt from <code>serviceproviders.xml</code>, which is
+usually found at <code>/usr/share/mobile-broadband-provider-info/serviceproviders.xml</code>
+on Debian/Ubuntu Linux systems.</p>
+
+<pre>
+d = xml.parse <span class="string">[[
+&lt;serviceproviders format="2.0"&gt;
+...
+&lt;country code="za"&gt;
+ &lt;provider&gt;
+ &lt;name&gt;Cell-c&lt;/name&gt;
+ &lt;gsm&gt;
+ &lt;network-id mcc="655" mnc="07"/&gt;
+ &lt;apn value="internet"&gt;
+ &lt;username&gt;Cellcis&lt;/username&gt;
+ &lt;dns&gt;196.7.0.138&lt;/dns&gt;
+ &lt;dns&gt;196.7.142.132&lt;/dns&gt;
+ &lt;/apn&gt;
+ &lt;/gsm&gt;
+ &lt;/provider&gt;
+ &lt;provider&gt;
+ &lt;name&gt;MTN&lt;/name&gt;
+ &lt;gsm&gt;
+ &lt;network-id mcc="655" mnc="10"/&gt;
+ &lt;apn value="internet"&gt;
+ &lt;dns&gt;196.11.240.241&lt;/dns&gt;
+ &lt;dns&gt;209.212.97.1&lt;/dns&gt;
+ &lt;/apn&gt;
+ &lt;/gsm&gt;
+ &lt;/provider&gt;
+ &lt;provider&gt;
+ &lt;name&gt;Vodacom&lt;/name&gt;
+ &lt;gsm&gt;
+ &lt;network-id mcc="655" mnc="01"/&gt;
+ &lt;apn value="internet"&gt;
+ &lt;dns&gt;196.207.40.165&lt;/dns&gt;
+ &lt;dns&gt;196.43.46.190&lt;/dns&gt;
+ &lt;/apn&gt;
+ &lt;apn value="unrestricted"&gt;
+ &lt;name&gt;Unrestricted&lt;/name&gt;
+ &lt;dns&gt;196.207.32.69&lt;/dns&gt;
+ &lt;dns&gt;196.43.45.190&lt;/dns&gt;
+ &lt;/apn&gt;
+ &lt;/gsm&gt;
+ &lt;/provider&gt;
+ &lt;provider&gt;
+ &lt;name&gt;Virgin Mobile&lt;/name&gt;
+ &lt;gsm&gt;
+ &lt;apn value="vdata"&gt;
+ &lt;dns&gt;196.7.0.138&lt;/dns&gt;
+ &lt;dns&gt;196.7.142.132&lt;/dns&gt;
+ &lt;/apn&gt;
+ &lt;/gsm&gt;
+ &lt;/provider&gt;
+&lt;/country&gt;
+....
+&lt;/serviceproviders&gt;
+]]</span>
+</pre>
+
+
+<p>Getting the names of the providers per-country is straightforward:</p>
+
+<pre>
+<span class="keyword">local</span> t = {}
+<span class="keyword">for</span> country <span class="keyword">in</span> d:childtags() <span class="keyword">do</span>
+ <span class="keyword">local</span> providers = {}
+ t[country.attr.code] = providers
+ <span class="keyword">for</span> provider <span class="keyword">in</span> country:childtags() <span class="keyword">do</span>
+ <span class="global">table</span>.insert(providers,provider:child_with_name(<span class="string">'name'</span>):get_text())
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+pretty.dump(t)
+<span class="comment">--&gt;
+</span>{
+ za = {
+ <span class="string">"Cell-c"</span>,
+ <span class="string">"MTN"</span>,
+ <span class="string">"Vodacom"</span>,
+ <span class="string">"Virgin Mobile"</span>
+ }
+ ....
+}
+</pre>
+
+
+<h4>Generating XML with &lsquo;xmlification&rsquo;</h4>
+
+<p>This feature is inspired by the <code>htmlify</code> function used by
+<a href="http://keplerproject.github.com/orbit/">Orbit</a> to simplify HTML generation,
+except that no function environment magic is used; the <code>tags</code> function returns a
+set of <em>constructors</em> for elements of the given tag names.</p>
+
+<pre>
+&gt; nodes, node = xml.tags <span class="string">'nodes, node'</span>
+&gt; = node <span class="string">'alice'</span>
+&lt;node&gt;alice&lt;/node&gt;
+&gt; = nodes { node {id=<span class="string">'1'</span>,<span class="string">'alice'</span>}}
+&lt;nodes&gt;&lt;node id=<span class="string">'1'</span>&gt;alice&lt;/node&gt;&lt;/nodes&gt;
+</pre>
+
+
+<p>The flexibility of Lua tables is very useful here, since both the attributes and
+the children of an element can be encoded naturally. The argument to these tag
+constructors is either a single value (like a string) or a table where the
+attributes are the named keys and the children are the array values.</p>
+
+<h4>Generating XML using Templates</h4>
+
+<p>A template is a little XML document which contains dollar-variables. The <code>subst</code>
+method on a document is fed an array of tables containing values for these
+variables. Note how the parent tag name is specified:</p>
+
+<pre>
+&gt; templ = xml.parse <span class="string">"&lt;node id='$id'&gt;$name&lt;/node&gt;"</span>
+&gt; = templ:subst {tag=<span class="string">'nodes'</span>, {id=<span class="number">1</span>,name=<span class="string">'alice'</span>},{id=<span class="number">2</span>,name=<span class="string">'john'</span>}}
+&lt;nodes&gt;&lt;node id=<span class="string">'1'</span>&gt;alice&lt;/node&gt;&lt;node id=<span class="string">'2'</span>&gt;john&lt;/node&gt;&lt;/nodes&gt;
+</pre>
+
+
+<p>Substitution is very related to <em>filtering</em> documents. One of the annoying things
+about XML is that it is a document markup language first, and a data language
+second. Standard parsers will assume you really care about all those extra
+text elements. Consider this fragment, which has been changed by a five-year old:</p>
+
+<pre>
+T = <span class="string">[[
+ &lt;weather&gt;
+ boops!
+ &lt;current_conditions&gt;
+ &lt;condition data='$condition'/&gt;
+ &lt;temp_c data='$temp'/&gt;
+ &lt;bo&gt;whoops!&lt;/bo&gt;
+ &lt;/current_conditions&gt;
+ &lt;/weather&gt;
+]]</span>
+</pre>
+
+
+<p>Conformant parsers will give you text elements with the line feed after <code>&lt;current_conditions&gt;</code>
+although it makes handling the data more irritating.</p>
+
+<pre>
+<span class="keyword">local</span> <span class="keyword">function</span> parse (str)
+ <span class="keyword">return</span> xml.parse(str,<span class="keyword">false</span>,<span class="keyword">true</span>)
+<span class="keyword">end</span>
+</pre>
+
+
+<p>Second argument means &lsquo;string, not file&rsquo; and third argument means use the built-in
+Lua parser (instead of LuaExpat if available) which <em>by default</em> is not interested in
+keeping such strings.</p>
+
+<p>How to remove the string <code>boops!</code>? <code>clone</code> (also called <a href="../libraries/pl.data.html#filter">filter</a> when called as a
+method) copies a LOM document. It can be passed a filter function, which is applied
+to each string found. The powerful thing about this is that this function receives
+structural information - the parent node, and whether this was a tag name, a text
+element or a attribute name:</p>
+
+<pre>
+d = parse (T)
+c = d:filter(<span class="keyword">function</span>(s,kind,parent)
+ <span class="global">print</span>(stringx.strip(s),kind,parent <span class="keyword">and</span> parent.tag <span class="keyword">or</span> <span class="string">'?'</span>)
+ <span class="keyword">if</span> kind == <span class="string">'*TEXT'</span> <span class="keyword">and</span> #parent &gt; <span class="number">1</span> <span class="keyword">then</span> <span class="keyword">return</span> <span class="keyword">nil</span> <span class="keyword">end</span>
+ <span class="keyword">return</span> s
+<span class="keyword">end</span>)
+<span class="comment">---&gt;
+</span>weather *TAG ?
+boops! *TEXT weather
+current_conditions *TAG weather
+condition *TAG current_conditions
+$condition data condition
+temp_c *TAG current_conditions
+$temp data temp_c
+bo *TAG current_conditions
+whoops! *TEXT bo
+</pre>
+
+
+<p>We can pull out &lsquo;boops&rsquo; and not &lsquo;whoops&rsquo; by discarding text elements which are not
+the single child of an element.</p>
+
+<h4>Extracting Data using Templates</h4>
+
+<p>Matching goes in the opposite direction. We have a document, and would like to
+extract values from it using a pattern.</p>
+
+<p>A common use of this is parsing the XML result of API queries. The
+<a href="http://blog.programmableweb.com/2010/02/08/googles-secret-weather-api/">(undocumented and subsequently discontinued) Google Weather
+API</a> is a
+good example. Grabbing the result of
+`http://www.google.com/ig/api?weather=Johannesburg,ZA" we get something like
+this, after pretty-printing:</p>
+
+<pre>
+&lt;xml_api_reply version=<span class="string">'1'</span>&gt;
+ &lt;weather module_id=<span class="string">'0'</span> tab_id=<span class="string">'0'</span> mobile_zipped=<span class="string">'1'</span> section=<span class="string">'0'</span> row=<span class="string">'0'</span>
+</pre>
+
+
+<p>mobile_row=&lsquo;0&rsquo;></p>
+
+<pre>
+&lt;forecast_information&gt;
+ &lt;city data=<span class="string">'Johannesburg, Gauteng'</span>/&gt;
+ &lt;postal_code data=<span class="string">'Johannesburg,ZA'</span>/&gt;
+ &lt;latitude_e6 data=<span class="string">''</span>/&gt;
+ &lt;longitude_e6 data=<span class="string">''</span>/&gt;
+ &lt;forecast_date data=<span class="string">'2010-10-02'</span>/&gt;
+ &lt;current_date_time data=<span class="string">'2010-10-02 18:30:00 +0000'</span>/&gt;
+ &lt;unit_system data=<span class="string">'US'</span>/&gt;
+&lt;/forecast_information&gt;
+&lt;current_conditions&gt;
+ &lt;condition data=<span class="string">'Clear'</span>/&gt;
+ &lt;temp_f data=<span class="string">'75'</span>/&gt;
+ &lt;temp_c data=<span class="string">'24'</span>/&gt;
+ &lt;humidity data=<span class="string">'Humidity: 19%'</span>/&gt;
+ &lt;icon data=<span class="string">'/ig/images/weather/sunny.gif'</span>/&gt;
+ &lt;wind_condition data=<span class="string">'Wind: NW at 7 mph'</span>/&gt;
+&lt;/current_conditions&gt;
+&lt;forecast_conditions&gt;
+ &lt;day_of_week data=<span class="string">'Sat'</span>/&gt;
+ &lt;low data=<span class="string">'60'</span>/&gt;
+ &lt;high data=<span class="string">'89'</span>/&gt;
+ &lt;icon data=<span class="string">'/ig/images/weather/sunny.gif'</span>/&gt;
+ &lt;condition data=<span class="string">'Clear'</span>/&gt;
+&lt;/forecast_conditions&gt;
+....
+/weather&gt;
+l_api_reply&gt;
+</pre>
+
+
+<p>Assume that the above XML has been read into <code>google</code>. The idea is to write a
+pattern looking like a template, and use it to extract some values of interest:</p>
+
+<pre>
+t = <span class="string">[[
+ &lt;weather&gt;
+ &lt;current_conditions&gt;
+ &lt;condition data='$condition'/&gt;
+ &lt;temp_c data='$temp'/&gt;
+ &lt;/current_conditions&gt;
+ &lt;/weather&gt;
+]]</span>
+
+<span class="keyword">local</span> res, ret = google:match(t)
+pretty.dump(res)
+</pre>
+
+
+<p>And the output is:</p>
+
+<pre>
+{
+ condition = <span class="string">"Clear"</span>,
+ temp = <span class="string">"24"</span>
+}
+</pre>
+
+
+<p>The <code>match</code> method can be passed a LOM document or some text, which will be
+parsed first.</p>
+
+<p>But what if we need to extract values from repeated elements? Match templates may
+contain &lsquo;array matches&rsquo; which are enclosed in &lsquo;{{..}}&rsquo;:</p>
+
+<pre>
+&lt;weather&gt;
+ {{&lt;forecast_conditions&gt;
+ &lt;day_of_week data=<span class="string">'$day'</span>/&gt;
+ &lt;low data=<span class="string">'$low'</span>/&gt;
+ &lt;high data=<span class="string">'$high'</span>/&gt;
+ &lt;condition data=<span class="string">'$condition'</span>/&gt;
+ &lt;/forecast_conditions&gt;}}
+&lt;/weather&gt;
+</pre>
+
+
+<p>And the match result is:</p>
+
+<pre>
+{
+ {
+ low = <span class="string">"60"</span>,
+ high = <span class="string">"89"</span>,
+ day = <span class="string">"Sat"</span>,
+ condition = <span class="string">"Clear"</span>,
+ },
+ {
+ low = <span class="string">"53"</span>,
+ high = <span class="string">"86"</span>,
+ day = <span class="string">"Sun"</span>,
+ condition = <span class="string">"Clear"</span>,
+ },
+ {
+ low = <span class="string">"57"</span>,
+ high = <span class="string">"87"</span>,
+ day = <span class="string">"Mon"</span>,
+ condition = <span class="string">"Clear"</span>,
+ },
+ {
+ low = <span class="string">"60"</span>,
+ high = <span class="string">"84"</span>,
+ day = <span class="string">"Tue"</span>,
+ condition = <span class="string">"Clear"</span>,
+ }
+}
+</pre>
+
+
+<p>With this array of tables, you can use <a href="../libraries/pl.tablex.html#">tablex</a> or <a href="../classes/pl.List.html#">List</a>
+to reshape into the desired form, if you choose. Just as with reading a Unix password
+file with <a href="../libraries/pl.config.html#">config</a>, you can make the array into a map of days to conditions using:</p>
+
+<pre>
+<span class="backtick"><a href="../libraries/pl.tablex.html#pairmap">tablex.pairmap</a></span>(<span class="string">'|k,v| v,v.day'</span>,conditions)
+</pre>
+
+
+<p>(Here using the alternative string lambda option)</p>
+
+<p>However, xml matches can shape the structure of the output. By replacing the <code>day_of_week</code>
+line of the template with <code>&lt;day_of_week data=&apos;$_&apos;/&gt;</code> we get the same effect; <code>$_</code> is
+a special symbol that means that this captured value (or simply <em>capture</em>) becomes the key.</p>
+
+<p>Note that <code>$NUMBER</code> means a numerical index, so
+that <code>$1</code> is the first element of the resulting array, and so forth. You can mix
+numbered and named captures, but it&rsquo;s strongly advised to make the numbered captures
+form a proper array sequence (everything from <code>1</code> to <code>n</code> inclusive). <code>$0</code> has a
+special meaning; if it is the only capture (<code>{[0]=&apos;foo&apos;}</code>) then the table is
+collapsed into &lsquo;foo&rsquo;.</p>
+
+<pre>
+&lt;weather&gt;
+ {{&lt;forecast_conditions&gt;
+ &lt;day_of_week data=<span class="string">'$_'</span>/&gt;
+ &lt;low data=<span class="string">'$1'</span>/&gt;
+ &lt;high data=<span class="string">'$2'</span>/&gt;
+ &lt;condition data=<span class="string">'$3'</span>/&gt;
+ &lt;/forecast_conditions&gt;}}
+&lt;/weather&gt;
+</pre>
+
+
+<p>Now the result is:</p>
+
+<pre>
+{
+ Tue = {
+ <span class="string">"60"</span>,
+ <span class="string">"84"</span>,
+ <span class="string">"Clear"</span>
+ },
+ Sun = {
+ <span class="string">"53"</span>,
+ <span class="string">"86"</span>,
+ <span class="string">"Clear"</span>
+ },
+ Sat = {
+ <span class="string">"60"</span>,
+ <span class="string">"89"</span>,
+ <span class="string">"Clear"</span>
+ },
+ Mon = {
+ <span class="string">"57"</span>,
+ <span class="string">"87"</span>,
+ <span class="string">"Clear"</span>
+ }
+}
+</pre>
+
+
+<p>Applying matches to this config file poses another problem, because the actual
+tags matched are themselves meaningful.</p>
+
+<pre>
+&lt;config&gt;
+ &lt;alpha&gt;<span class="number">1.3</span>&lt;/alpha&gt;
+ &lt;beta&gt;<span class="number">10</span>&lt;/beta&gt;
+ &lt;name&gt;bozo&lt;/name&gt;
+&lt;/config&gt;
+</pre>
+
+
+<p>So there are tag &lsquo;wildcards&rsquo; which are element names ending with a hyphen.</p>
+
+<pre>
+&lt;config&gt;
+ {{&lt;key-&gt;$value&lt;/key-&gt;}}
+&lt;/config&gt;
+</pre>
+
+
+<p>You will then get <code>{{alpha=&apos;1.3&apos;},&hellip;}</code>. The most convenient format would be
+returned by this (note that <code>_-</code> behaves just like <code>$_</code>):</p>
+
+<pre>
+&lt;config&gt;
+ {{&lt;_-&gt;$<span class="number">0</span>&lt;/_-&gt;}}
+&lt;/config&gt;
+</pre>
+
+
+<p>which would return <code>{alpha=&apos;1.3&apos;,beta=&apos;10&apos;,name=&apos;bozo&apos;}</code>.</p>
+
+<p>We could play this game endlessly, and encode ways of converting captures, but
+the scheme is complex enough, and it&rsquo;s easy to do the conversion later</p>
+
+<pre>
+<span class="keyword">local</span> numbers = {alpha=<span class="keyword">true</span>,beta=<span class="keyword">true</span>}
+<span class="keyword">for</span> k,v <span class="keyword">in</span> <span class="global">pairs</span>(res) <span class="keyword">do</span>
+ <span class="keyword">if</span> numbers[v] <span class="keyword">then</span> res[k] = <span class="global">tonumber</span>(v) <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<h4>HTML Parsing</h4>
+
+<p>HTML is an unusually degenerate form of XML, and Dennis Schridde has contributed
+a feature which makes parsing it easier. For instance, from the tests:</p>
+
+<pre>
+doc = xml.parsehtml <span class="string">[[
+&lt;BODY&gt;
+Hello dolly&lt;br&gt;
+HTML is &lt;b&gt;slack&lt;/b&gt;&lt;br&gt;
+&lt;/BODY&gt;
+]]</span>
+
+asserteq(xml.<span class="global">tostring</span>(doc),<span class="string">[[
+&lt;body&gt;
+Hello dolly&lt;br/&gt;
+HTML is &lt;b&gt;slack&lt;/b&gt;&lt;br/&gt;&lt;/body&gt;]]</span>)
+</pre>
+
+
+<p>That is, all tags are converted to lowercase, and empty HTML elements like <code>br</code>
+are properly closed; attributes do not need to be quoted.</p>
+
+<p>Also, DOCTYPE directives and comments are skipped. For truly badly formed HTML,
+this is not the tool for you!</p>
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/07-functional.md.html b/docs/manual/07-functional.md.html
new file mode 100644
index 0000000..c093eef
--- /dev/null
+++ b/docs/manual/07-functional.md.html
@@ -0,0 +1,835 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Sequences">Sequences </a></li>
+<li><a href="#Sequence_Wrappers">Sequence Wrappers </a></li>
+<li><a href="#List_Comprehensions">List Comprehensions </a></li>
+<li><a href="#Creating_Functions_from_Functions">Creating Functions from Functions </a></li>
+<li><a href="#Placeholder_Expressions">Placeholder Expressions </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><strong>Functional Programming</strong></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Functional Programming</h2>
+
+<p><a name="Sequences"></a></p>
+
+<h3>Sequences</h3>
+
+<p>A Lua iterator (in its simplest form) is a function which can be repeatedly
+called to return a set of one or more values. The <code>for in</code> statement understands
+these iterators, and loops until the function returns <code>nil</code>. There are standard
+sequence adapters for tables in Lua (<a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a> and <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a>), and <a href="https://www.lua.org/manual/5.1/manual.html#pdf-io.lines">io.lines</a>
+returns an iterator over all the lines in a file. In the Penlight libraries, such
+iterators are also called <em>sequences</em>. A sequence of single values (say from
+<a href="https://www.lua.org/manual/5.1/manual.html#pdf-io.lines">io.lines</a>) is called <em>single-valued</em>, whereas the sequence defined by <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a> is
+<em>double-valued</em>.</p>
+
+<p><a href="../libraries/pl.seq.html#">pl.seq</a> provides a number of useful iterators, and some functions which operate
+on sequences. At first sight this example looks like an attempt to write Python
+in Lua, (with the sequence being inclusive):</p>
+
+<pre>
+&gt; <span class="keyword">for</span> i <span class="keyword">in</span> seq.range(<span class="number">1</span>,<span class="number">4</span>) <span class="keyword">do</span> <span class="global">print</span>(i) <span class="keyword">end</span>
+<span class="number">1</span>
+<span class="number">2</span>
+<span class="number">3</span>
+<span class="number">4</span>
+</pre>
+
+
+<p>But <a href="../libraries/pl.seq.html#range">range</a> is actually equivalent to Python&rsquo;s <code>xrange</code>, since it generates a
+sequence, not a list. To get a list, use <code>seq.copy(seq.range(1,10))</code>, which
+takes any single-value sequence and makes a table from the result. <a href="../libraries/pl.seq.html#list">seq.list</a> is
+like <a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a> except that it does not give you the index, just the value.</p>
+
+<pre>
+&gt; <span class="keyword">for</span> x <span class="keyword">in</span> seq.list {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>} <span class="keyword">do</span> <span class="global">print</span>(x) <span class="keyword">end</span>
+<span class="number">1</span>
+<span class="number">2</span>
+<span class="number">3</span>
+</pre>
+
+
+<p><a href="../libraries/pl.seq.html#enum">enum</a> takes a sequence and turns it into a double-valued sequence consisting of
+a sequence number and the value, so <code>enum(list(ls))</code> is actually equivalent to
+<a href="https://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a>. A more interesting example prints out a file with line numbers:</p>
+
+<pre>
+<span class="keyword">for</span> i,v <span class="keyword">in</span> seq.enum(<span class="global">io</span>.lines(fname)) <span class="keyword">do</span> <span class="global">print</span>(i..<span class="string">' '</span>..v) <span class="keyword">end</span>
+</pre>
+
+
+<p>Sequences can be <em>combined</em>, either by &lsquo;zipping&rsquo; them or by concatenating them.</p>
+
+<pre>
+&gt; <span class="keyword">for</span> x,y <span class="keyword">in</span> seq.zip(l1,l2) <span class="keyword">do</span> <span class="global">print</span>(x,y) <span class="keyword">end</span>
+<span class="number">10</span> <span class="number">1</span>
+<span class="number">20</span> <span class="number">2</span>
+<span class="number">30</span> <span class="number">3</span>
+&gt; <span class="keyword">for</span> x <span class="keyword">in</span> seq.splice(l1,l2) <span class="keyword">do</span> <span class="global">print</span>(x) <span class="keyword">end</span>
+<span class="number">10</span>
+<span class="number">20</span>
+<span class="number">30</span>
+<span class="number">1</span>
+<span class="number">2</span>
+<span class="number">3</span>
+</pre>
+
+
+<p><a href="../libraries/pl.seq.html#printall">seq.printall</a> is useful for printing out single-valued sequences, and provides
+some finer control over formating, such as a delimiter, the number of fields per
+line, and a format string to use (@see string.format)</p>
+
+<pre>
+&gt; seq.printall(seq.random(<span class="number">10</span>))
+<span class="number">0.0012512588885159</span> <span class="number">0.56358531449324</span> <span class="number">0.19330423902097</span> ....
+&gt; seq.printall(seq.random(<span class="number">10</span>), <span class="string">','</span>, <span class="number">4</span>, <span class="string">'%4.2f'</span>)
+<span class="number">0.17</span>,<span class="number">0.86</span>,<span class="number">0.71</span>,<span class="number">0.51</span>
+<span class="number">0.30</span>,<span class="number">0.01</span>,<span class="number">0.09</span>,<span class="number">0.36</span>
+<span class="number">0.15</span>,<span class="number">0.17</span>,
+</pre>
+
+
+<p><a href="../libraries/pl.seq.html#map">map</a> will apply a function to a sequence.</p>
+
+<pre>
+&gt; seq.printall(seq.map(<span class="global">string</span>.upper, {<span class="string">'one'</span>,<span class="string">'two'</span>}))
+ONE TWO
+&gt; seq.printall(seq.map(<span class="string">'+'</span>, {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}, <span class="number">1</span>))
+<span class="number">11</span> <span class="number">21</span> <span class="number">31</span>
+</pre>
+
+
+<p><a href="../libraries/pl.seq.html#filter">filter</a> will filter a sequence using a boolean function (often called a
+<em>predicate</em>). For instance, this code only prints lines in a file which are
+composed of digits:</p>
+
+<pre>
+<span class="keyword">for</span> l <span class="keyword">in</span> seq.filter(<span class="global">io</span>.lines(file), stringx.isdigit) <span class="keyword">do</span> <span class="global">print</span>(l) <span class="keyword">end</span>
+</pre>
+
+
+<p>The following returns a table consisting of all the positive values in the
+original table (equivalent to <code>tablex.filter(ls, &apos;&gt;&apos;, 0)</code>)</p>
+
+<pre>
+ls = seq.copy(seq.filter(ls, <span class="string">'&gt;'</span>, <span class="number">0</span>))
+</pre>
+
+
+<p>We&rsquo;re already encounted <a href="../libraries/pl.seq.html#sum">seq.sum</a> when discussing <a href="../libraries/pl.input.html#numbers">input.numbers</a>. This can also
+be expressed with <a href="../libraries/pl.seq.html#reduce">seq.reduce</a>:</p>
+
+<pre>
+&gt; seq.reduce(<span class="keyword">function</span>(x,y) <span class="keyword">return</span> x + y <span class="keyword">end</span>, seq.list{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+<span class="number">10</span>
+</pre>
+
+
+<p><a href="../libraries/pl.seq.html#reduce">seq.reduce</a> applies a binary function in a recursive fashion, so that:</p>
+
+<pre>
+reduce(op,{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}) =&gt; op(<span class="number">1</span>,reduce(op,{<span class="number">2</span>,<span class="number">3</span>}) =&gt; op(<span class="number">1</span>,op(<span class="number">2</span>,<span class="number">3</span>))
+</pre>
+
+
+<p>it&rsquo;s now possible to easily generate other cumulative operations; the standard
+operations declared in <a href="../libraries/pl.operator.html#">pl.operator</a> are useful here:</p>
+
+<pre>
+&gt; ops = <span class="global">require</span> <span class="string">'pl.operator'</span>
+&gt; <span class="comment">-- can also say '*' instead of ops.mul
+</span>&gt; = seq.reduce(ops.mul,input.numbers <span class="string">'1 2 3 4'</span>)
+<span class="number">24</span>
+</pre>
+
+
+<p>There are functions to extract statistics from a sequence of numbers:</p>
+
+<pre>
+&gt; l1 = List {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}
+&gt; l2 = List {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
+&gt; = seq.minmax(l1)
+<span class="number">10</span> <span class="number">30</span>
+&gt; = seq.sum(l1)
+<span class="number">60</span> <span class="number">3</span>
+</pre>
+
+
+<p>It is common to get sequences where values are repeated, say the words in a file.
+<a href="../libraries/pl.seq.html#count_map">count_map</a> will take such a sequence and count the values, returning a table
+where the <em>keys</em> are the unique values, and the value associated with each key is
+the number of times they occurred:</p>
+
+<pre>
+&gt; t = seq.count_map {<span class="string">'one'</span>,<span class="string">'fred'</span>,<span class="string">'two'</span>,<span class="string">'one'</span>,<span class="string">'two'</span>,<span class="string">'two'</span>}
+&gt; = t
+{one=<span class="number">2</span>,fred=<span class="number">1</span>,two=<span class="number">3</span>}
+</pre>
+
+
+<p>This will also work on numerical sequences, but you cannot expect the result to
+be a proper list, i.e. having no &lsquo;holes&rsquo;. Instead, you always need to use <a href="https://www.lua.org/manual/5.1/manual.html#pdf-pairs">pairs</a>
+to iterate over the result - note that there is a hole at index 5:</p>
+
+<pre>
+&gt; t = seq.count_map {<span class="number">1</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">2</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">2</span>,<span class="number">6</span>}
+&gt; <span class="keyword">for</span> k,v <span class="keyword">in</span> <span class="global">pairs</span>(t) <span class="keyword">do</span> <span class="global">print</span>(k,v) <span class="keyword">end</span>
+<span class="number">1</span> <span class="number">1</span>
+<span class="number">2</span> <span class="number">4</span>
+<span class="number">3</span> <span class="number">1</span>
+<span class="number">4</span> <span class="number">2</span>
+<span class="number">6</span> <span class="number">1</span>
+</pre>
+
+
+<p><code>unique</code> uses <a href="../libraries/pl.seq.html#count_map">count_map</a> to return a list of the unique values, that is, just
+the keys of the resulting table.</p>
+
+<p><a href="../libraries/pl.seq.html#last">last</a> turns a single-valued sequence into a double-valued sequence with the
+current value and the last value:</p>
+
+<pre>
+&gt; <span class="keyword">for</span> current,last <span class="keyword">in</span> seq.last {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>} <span class="keyword">do</span> <span class="global">print</span> (current,last) <span class="keyword">end</span>
+<span class="number">20</span> <span class="number">10</span>
+<span class="number">30</span> <span class="number">20</span>
+<span class="number">40</span> <span class="number">30</span>
+</pre>
+
+
+<p>This makes it easy to do things like identify repeated lines in a file, or
+construct differences between values. <a href="../libraries/pl.seq.html#filter">filter</a> can handle double-valued sequences
+as well, so one could filter such a sequence to only return cases where the
+current value is less than the last value by using <a href="../libraries/pl.operator.html#lt">operator.lt</a> or just &lsquo;&lt;&rsquo;.
+This code then copies the resulting code into a table.</p>
+
+<pre>
+&gt; ls = {<span class="number">10</span>,<span class="number">9</span>,<span class="number">10</span>,<span class="number">3</span>}
+&gt; = seq.copy(seq.filter(seq.last(s),<span class="string">'&lt;'</span>))
+{<span class="number">9</span>,<span class="number">3</span>}
+</pre>
+
+
+<p><a name="Sequence_Wrappers"></a></p>
+
+<h3>Sequence Wrappers</h3>
+
+<p>The functions in <a href="../libraries/pl.seq.html#">pl.seq</a> cover the common patterns when dealing with sequences,
+but chaining these functions together can lead to ugly code. Consider the last
+example of the previous section; <a href="../libraries/pl.seq.html#">seq</a> is repeated three times and the resulting
+expression has to be read right-to-left. The first issue can be helped by local
+aliases, so that the expression becomes <code>copy(filter(last(s),&apos;&lt;&apos;))</code> but the
+second issue refers to the somewhat unnatural order of functional application.
+We tend to prefer reading operations from left to right, which is one reason why
+object-oriented notation has become popular. Sequence adapters allow this
+expression to be written like so:</p>
+
+<pre>
+seq(s):last():filter(<span class="string">'&lt;'</span>):copy()
+</pre>
+
+
+<p>With this notation, the operation becomes a chain of method calls running from
+left to right.</p>
+
+<p>&lsquo;Sequence&rsquo; is not a basic Lua type, they are generally functions or callable
+objects. The expression <code>seq(s)</code> wraps a sequence in a <em>sequence wrapper</em>, which
+is an object which understands all the functions in <a href="../libraries/pl.seq.html#">pl.seq</a> as methods. This
+object then explicitly represents sequences.</p>
+
+<p>As a special case, the constructor (which is when you call the table <a href="../libraries/pl.seq.html#">seq</a>) will
+make a wrapper for a plain list-like table. Here we apply the length operator to
+a sequence of strings, and print them out.</p>
+
+<pre>
+&gt; seq{<span class="string">'one'</span>,<span class="string">'tw'</span>,<span class="string">'t'</span>} :map <span class="string">'#'</span> :printall()
+<span class="number">3</span> <span class="number">2</span> <span class="number">1</span>
+</pre>
+
+
+<p>As a convenience, there is a function <a href="../libraries/pl.seq.html#lines">seq.lines</a> which behaves just like
+<a href="https://www.lua.org/manual/5.1/manual.html#pdf-io.lines">io.lines</a> except it wraps the result as an explicit sequence type. This takes
+the first 10 lines from standard input, makes it uppercase, turns it into a
+sequence with a count and the value, glues these together with the concatenation
+operator, and finally prints out the sequence delimited by a newline.</p>
+
+<pre>
+seq.lines():take(<span class="number">10</span>):upper():enum():map(<span class="string">'..'</span>):printall <span class="string">'\n'</span>
+</pre>
+
+
+<p>Note the method <code>upper</code>, which is not a <a href="../libraries/pl.seq.html#">seq</a> function. if an unknown method is
+called, sequence wrappers apply that method to all the values in the sequence
+(this is implicit use of <a href="../libraries/pl.seq.html#mapmethod">mapmethod</a>)</p>
+
+<p>It is straightforward to create custom sequences that can be used in this way. On
+Unix, <code>/dev/random</code> gives you an <em>endless</em> sequence of random bytes, so we use
+<a href="../libraries/pl.seq.html#take">take</a> to limit the sequence, and then <a href="../libraries/pl.seq.html#map">map</a> to scale the result into the desired
+range. The key step is to use <a href="../libraries/pl.seq.html#">seq</a> to wrap the iterator function:</p>
+
+<pre>
+<span class="comment">-- random.lua
+</span><span class="keyword">local</span> seq = <span class="global">require</span> <span class="string">'pl.seq'</span>
+
+<span class="keyword">function</span> dev_random()
+ <span class="keyword">local</span> f = <span class="global">io</span>.open(<span class="string">'/dev/random'</span>)
+ <span class="keyword">local</span> byte = <span class="global">string</span>.byte
+ <span class="keyword">return</span> seq(<span class="keyword">function</span>()
+ <span class="comment">-- read two bytes into a string and convert into a 16-bit number
+</span> <span class="keyword">local</span> s = f:read(<span class="number">2</span>)
+ <span class="keyword">return</span> byte(s,<span class="number">1</span>) + <span class="number">256</span>*byte(s,<span class="number">2</span>)
+ <span class="keyword">end</span>)
+<span class="keyword">end</span>
+
+<span class="comment">-- print 10 random numbers from 0 to 1 !
+</span>dev_random():take(<span class="number">10</span>):map(<span class="string">'%'</span>,<span class="number">100</span>):map(<span class="string">'/'</span>,<span class="number">100</span>):printall <span class="string">','</span>
+</pre>
+
+
+<p>Another Linux one-liner depends on the <code>/proc</code> filesystem and makes a list of all
+the currently running processes:</p>
+
+<pre>
+pids = seq(lfs.dir <span class="string">'/proc'</span>):filter(stringx.isdigit):map(<span class="global">tonumber</span>):copy()
+</pre>
+
+
+<p>This version of Penlight has an experimental feature which relies on the fact
+that <em>all</em> Lua types can have metatables, including functions. This makes
+<em>implicit sequence wrapping</em> possible:</p>
+
+<pre>
+&gt; seq.import()
+&gt; seq.random(<span class="number">5</span>):printall(<span class="string">','</span>,<span class="number">5</span>,<span class="string">'%4.1f'</span>)
+ <span class="number">0.0</span>, <span class="number">0.1</span>, <span class="number">0.4</span>, <span class="number">0.1</span>, <span class="number">0.2</span>
+</pre>
+
+
+<p>This avoids the awkward <code>seq(seq.random(5))</code> construction. Or the iterator can
+come from somewhere else completely:</p>
+
+<pre>
+&gt; (<span class="string">'one two three'</span>):gfind(<span class="string">'%a+'</span>):printall(<span class="string">','</span>)
+one,two,three,
+</pre>
+
+
+<p>After <code>seq.import</code>, it is no longer necessary to explicitly wrap sequence
+functions.</p>
+
+<p>But there is a price to pay for this convenience. <em>Every</em> function is affected,
+so that any function can be used, appropriate or not:</p>
+
+<pre>
+&gt; <span class="global">math</span>.sin:printall()
+..seq.lua:<span class="number">287</span>: bad argument #<span class="number">1</span> to <span class="string">'(for generator)'</span> (number expected, got <span class="keyword">nil</span>)
+&gt; a = <span class="global">tostring</span>
+&gt; = a:find(<span class="string">' '</span>)
+<span class="keyword">function</span>: <span class="number">0042</span>C920
+</pre>
+
+
+<p>What function is returned? It&rsquo;s almost certain to be something that makes no
+sense in the current context. So implicit sequences may make certain kinds of
+programming mistakes harder to catch - they are best used for interactive
+exploration and small scripts.</p>
+
+<p><a id="comprehensions"/></p>
+
+<p><a name="List_Comprehensions"></a></p>
+
+<h3>List Comprehensions</h3>
+
+<p>List comprehensions are a compact way to create tables by specifying their
+elements. In Python, you can say this:</p>
+
+<pre>
+ls = [x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">5</span>)] # == [<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]
+</pre>
+
+
+<p>In Lua, using <a href="../libraries/pl.comprehension.html#">pl.comprehension</a>:</p>
+
+<pre>
+&gt; C = <span class="global">require</span>(<span class="string">'pl.comprehension'</span>).new()
+&gt; = C (<span class="string">'x for x=1,10'</span>) ()
+{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>,<span class="number">10</span>}
+</pre>
+
+
+<p><code>C</code> is a function which compiles a list comprehension <em>string</em> into a <em>function</em>.
+In this case, the function has no arguments. The parentheses are redundant for a
+function taking a string argument, so this works as well:</p>
+
+<pre>
+&gt; = C <span class="string">'x^2 for x=1,4'</span> ()
+{<span class="number">1</span>,<span class="number">4</span>,<span class="number">9</span>,<span class="number">16</span>}
+&gt; = C <span class="string">'{x,x^2} for x=1,4'</span> ()
+{{<span class="number">1</span>,<span class="number">1</span>},{<span class="number">2</span>,<span class="number">4</span>},{<span class="number">3</span>,<span class="number">9</span>},{<span class="number">4</span>,<span class="number">16</span>}}
+</pre>
+
+
+<p>Note that the expression can be <em>any</em> function of the variable <code>x</code>!</p>
+
+<p>The basic syntax so far is <code>&lt;expr&gt; for &lt;set&gt;</code>, where <code>&lt;set&gt;</code> can be anything that
+the Lua <code>for</code> statement understands. <code>&lt;set&gt;</code> can also just be the variable, in
+which case the values will come from the <em>argument</em> of the comprehension. Here
+I&rsquo;m emphasizing that a comprehension is a function which can take a list argument:</p>
+
+<pre>
+&gt; = C <span class="string">'2*x for x'</span> {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}
+{<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>}
+&gt; dbl = C <span class="string">'2*x for x'</span>
+&gt; = dbl {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}
+{<span class="number">20</span>,<span class="number">40</span>,<span class="number">60</span>}
+</pre>
+
+
+<p>Here is a somewhat more explicit way of saying the same thing; <code>_1</code> is a
+<em>placeholder</em> refering to the <em>first</em> argument passed to the comprehension.</p>
+
+<pre>
+&gt; = C <span class="string">'2*x for _,x in pairs(_1)'</span> {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>}
+{<span class="number">20</span>,<span class="number">40</span>,<span class="number">60</span>}
+&gt; = C <span class="string">'_1(x) for x'</span>(<span class="global">tostring</span>,{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+{<span class="string">'1'</span>,<span class="string">'2'</span>,<span class="string">'3'</span>,<span class="string">'4'</span>}
+</pre>
+
+
+<p>This extended syntax is useful when you wish to collect the result of some
+iterator, such as <a href="https://www.lua.org/manual/5.1/manual.html#pdf-io.lines">io.lines</a>. This comprehension creates a function which creates
+a table of all the lines in a file:</p>
+
+<pre>
+&gt; f = <span class="global">io</span>.open(<span class="string">'array.lua'</span>)
+&gt; lines = C <span class="string">'line for line in _1:lines()'</span> (f)
+&gt; = #lines
+<span class="number">118</span>
+</pre>
+
+
+<p>There are a number of functions that may be applied to the result of a
+comprehension:</p>
+
+<pre>
+&gt; = C <span class="string">'min(x for x)'</span> {<span class="number">1</span>,<span class="number">44</span>,<span class="number">0</span>}
+<span class="number">0</span>
+&gt; = C <span class="string">'max(x for x)'</span> {<span class="number">1</span>,<span class="number">44</span>,<span class="number">0</span>}
+<span class="number">44</span>
+&gt; = C <span class="string">'sum(x for x)'</span> {<span class="number">1</span>,<span class="number">44</span>,<span class="number">0</span>}
+<span class="number">45</span>
+</pre>
+
+
+<p>(These are equivalent to a reduce operation on a list.)</p>
+
+<p>After the <code>for</code> part, there may be a condition, which filters the output. This
+comprehension collects the even numbers from a list:</p>
+
+<pre>
+&gt; = C <span class="string">'x for x if x % 2 == 0'</span> {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>}
+{<span class="number">2</span>,<span class="number">4</span>}
+</pre>
+
+
+<p>There may be a number of <code>for</code> parts:</p>
+
+<pre>
+&gt; = C <span class="string">'{x,y} for x = 1,2 for y = 1,2'</span> ()
+{{<span class="number">1</span>,<span class="number">1</span>},{<span class="number">1</span>,<span class="number">2</span>},{<span class="number">2</span>,<span class="number">1</span>},{<span class="number">2</span>,<span class="number">2</span>}}
+&gt; = C <span class="string">'{x,y} for x for y'</span> ({<span class="number">1</span>,<span class="number">2</span>},{<span class="number">10</span>,<span class="number">20</span>})
+{{<span class="number">1</span>,<span class="number">10</span>},{<span class="number">1</span>,<span class="number">20</span>},{<span class="number">2</span>,<span class="number">10</span>},{<span class="number">2</span>,<span class="number">20</span>}}
+</pre>
+
+
+<p>These comprehensions are useful when dealing with functions of more than one
+variable, and are not so easily achieved with the other Penlight functional forms.</p>
+
+<p><a id="func"/></p>
+
+<p><a name="Creating_Functions_from_Functions"></a></p>
+
+<h3>Creating Functions from Functions</h3>
+
+<p>Lua functions may be treated like any other value, although of course you cannot
+multiply or add them. One operation that makes sense is <em>function composition</em>,
+which chains function calls (so <code>(f * g)(x)</code> is <code>f(g(x))</code>.)</p>
+
+<pre>
+&gt; func = <span class="global">require</span> <span class="string">'pl.func'</span>
+&gt; printf = func.compose(<span class="global">io</span>.write,<span class="global">string</span>.format)
+&gt; printf(<span class="string">"hello %s\n"</span>,<span class="string">'world'</span>)
+hello world
+<span class="keyword">true</span>
+</pre>
+
+
+<p>Many functions require you to pass a function as an argument, say to apply to all
+values of a sequence or as a callback. Often useful functions have the wrong
+number of arguments. So there is a need to construct a function of one argument
+from one of two arguments, <em>binding</em> the extra argument to a given value.</p>
+
+<p><em>partial application</em> takes a function of n arguments and returns a function of n-1
+arguments where the first argument is bound to some value:</p>
+
+<pre>
+&gt; p2 = func.bind1(<span class="global">print</span>,<span class="string">'start&gt;'</span>)
+&gt; p2(<span class="string">'hello'</span>,<span class="number">2</span>)
+start&gt; hello <span class="number">2</span>
+&gt; ops = <span class="global">require</span> <span class="string">'pl.operator'</span>
+&gt; = tablex.filter({<span class="number">1</span>,-<span class="number">2</span>,<span class="number">10</span>,-<span class="number">1</span>,<span class="number">2</span>},bind1(ops.gt,<span class="number">0</span>))
+{-<span class="number">2</span>,-<span class="number">1</span>}
+&gt; tablex.filter({<span class="number">1</span>,-<span class="number">2</span>,<span class="number">10</span>,-<span class="number">1</span>,<span class="number">2</span>},bind1(ops.le,<span class="number">0</span>))
+{<span class="number">1</span>,<span class="number">10</span>,<span class="number">2</span>}
+</pre>
+
+
+<p>The last example unfortunately reads backwards, because <a href="../libraries/pl.func.html#bind1">bind1</a> alway binds the
+first argument! Also unfortunately, in my youth I confused &lsquo;currying&rsquo; with
+&lsquo;partial application&rsquo;, so the old name for <a href="../libraries/pl.func.html#bind1">bind1</a> is <code>curry</code> - this alias still exists.</p>
+
+<p>This is a specialized form of function argument binding. Here is another way
+to say the <a href="https://www.lua.org/manual/5.1/manual.html#pdf-print">print</a> example:</p>
+
+<pre>
+&gt; p2 = func.bind(<span class="global">print</span>,<span class="string">'start&gt;'</span>,func._1,func._2)
+&gt; p2(<span class="string">'hello'</span>,<span class="number">2</span>)
+start&gt; hello <span class="number">2</span>
+</pre>
+
+
+<p>where <code>_1</code> and <code>_2</code> are <em>placeholder variables</em>, corresponding to the first and
+second argument respectively.</p>
+
+<p>Having <a href="../libraries/pl.func.html#">func</a> all over the place is distracting, so it&rsquo;s useful to pull all of
+<a href="../libraries/pl.func.html#">pl.func</a> into the local context. Here is the filter example, this time the right
+way around:</p>
+
+<pre>
+&gt; utils.import <span class="string">'pl.func'</span>
+&gt; tablex.filter({<span class="number">1</span>,-<span class="number">2</span>,<span class="number">10</span>,-<span class="number">1</span>,<span class="number">2</span>},bind(ops.gt, _1, <span class="number">0</span>))
+{<span class="number">1</span>,<span class="number">10</span>,<span class="number">2</span>}
+</pre>
+
+
+<p><a href="../libraries/pl.tablex.html#merge">tablex.merge</a> does a general merge of two tables. This example shows the
+usefulness of binding the last argument of a function.</p>
+
+<pre>
+&gt; S1 = {john=<span class="number">27</span>, jane=<span class="number">31</span>, mary=<span class="number">24</span>}
+&gt; S2 = {jane=<span class="number">31</span>, jones=<span class="number">50</span>}
+&gt; intersection = bind(tablex.merge, _1, _2, <span class="keyword">false</span>)
+&gt; union = bind(tablex.merge, _1, _2, <span class="keyword">true</span>)
+&gt; = intersection(S1,S2)
+{jane=<span class="number">31</span>}
+&gt; = union(S1,S2)
+{mary=<span class="number">24</span>,jane=<span class="number">31</span>,john=<span class="number">27</span>,jones=<span class="number">50</span>}
+</pre>
+
+
+<p>When using <a href="../libraries/pl.func.html#bind">bind</a> with <a href="https://www.lua.org/manual/5.1/manual.html#pdf-print">print</a>, we got a function of precisely two arguments,
+whereas we really want our function to use varargs like <a href="https://www.lua.org/manual/5.1/manual.html#pdf-print">print</a>. This is the role
+of <code>_0</code>:</p>
+
+<pre>
+&gt; _DEBUG = <span class="keyword">true</span>
+&gt; p = bind(<span class="global">print</span>,<span class="string">'start&gt;'</span>, _0)
+<span class="keyword">return</span> <span class="keyword">function</span> (fn,_v1)
+ <span class="keyword">return</span> <span class="keyword">function</span>(...) <span class="keyword">return</span> fn(_v1,...) <span class="keyword">end</span>
+<span class="keyword">end</span>
+
+&gt; p(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>)
+start&gt; <span class="number">1</span> <span class="number">2</span> <span class="number">3</span> <span class="number">4</span> <span class="number">5</span>
+</pre>
+
+
+<p>I&rsquo;ve turned on the global <code>_DEBUG</code> flag, so that the function generated is
+printed out. It is actually a function which <em>generates</em> the required function;
+the first call <em>binds the value</em> of <code>_v1</code> to &lsquo;start>&rsquo;.</p>
+
+<p><a name="Placeholder_Expressions"></a></p>
+
+<h3>Placeholder Expressions</h3>
+
+<p>A common pattern in Penlight is a function which applies another function to all
+elements in a table or a sequence, such as <a href="../libraries/pl.tablex.html#map">tablex.map</a> or <a href="../libraries/pl.seq.html#filter">seq.filter</a>. Lua does
+anonymous functions well, although they can be a bit tedious to type:</p>
+
+<pre>
+&gt; = tablex.map(<span class="keyword">function</span>(x) <span class="keyword">return</span> x*x <span class="keyword">end</span>, {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+{<span class="number">1</span>,<span class="number">4</span>,<span class="number">9</span>,<span class="number">16</span>}
+</pre>
+
+
+<p><a href="../libraries/pl.func.html#">pl.func</a> allows you to define <em>placeholder expressions</em>, which can cut down on
+the typing required, and also make your intent clearer. First, we bring contents
+of <a href="../libraries/pl.func.html#">pl.func</a> into our context, and then supply an expression using placeholder
+variables, such as <code>_1</code>,<code>_2</code>,etc. (C++ programmers will recognize this from the
+Boost libraries.)</p>
+
+<pre>
+&gt; utils.import <span class="string">'pl.func'</span>
+&gt; = tablex.map(_1*_1, {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+{<span class="number">1</span>,<span class="number">4</span>,<span class="number">9</span>,<span class="number">16</span>}
+</pre>
+
+
+<p>Functions of up to 5 arguments can be generated.</p>
+
+<pre>
+&gt; = tablex.map2(_1+_2,{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>}, {<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>})
+{<span class="number">11</span>,<span class="number">22</span>,<span class="number">33</span>}
+</pre>
+
+
+<p>These expressions can use arbitrary functions, altho they must first be
+registered with the functional library. <a href="../libraries/pl.func.html#register">func.register</a> brings in a single
+function, and <a href="../libraries/pl.func.html#import">func.import</a> brings in a whole table of functions, such as <a href="https://www.lua.org/manual/5.1/manual.html#5.6">math</a>.</p>
+
+<pre>
+&gt; sin = register(<span class="global">math</span>.sin)
+&gt; = tablex.map(sin(_1), {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+{<span class="number">0.8414709848079</span>,<span class="number">0.90929742682568</span>,<span class="number">0.14112000805987</span>,-<span class="number">0.75680249530793</span>}
+&gt; import <span class="string">'math'</span>
+&gt; = tablex.map(cos(<span class="number">2</span>*_1),{<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>})
+{-<span class="number">0.41614683654714</span>,-<span class="number">0.65364362086361</span>,<span class="number">0.96017028665037</span>,-<span class="number">0.14550003380861</span>}
+</pre>
+
+
+<p>A common operation is calling a method of a set of objects:</p>
+
+<pre>
+&gt; = tablex.map(_1:sub(<span class="number">1</span>,<span class="number">1</span>), {<span class="string">'one'</span>,<span class="string">'four'</span>,<span class="string">'x'</span>})
+{<span class="string">'o'</span>,<span class="string">'f'</span>,<span class="string">'x'</span>}
+</pre>
+
+
+<p>There are some restrictions on what operators can be used in PEs. For instance,
+because the <code>__len</code> metamethod cannot be overriden by plain Lua tables, we need
+to define a special function to express `#_1':</p>
+
+<pre>
+&gt; = tablex.map(Len(_1), {<span class="string">'one'</span>,<span class="string">'four'</span>,<span class="string">'x'</span>})
+{<span class="number">3</span>,<span class="number">4</span>,<span class="number">1</span>}
+</pre>
+
+
+<p>Likewise for comparison operators, which cannot be overloaded for <em>different</em>
+types, and thus also have to be expressed as a special function:</p>
+
+<pre>
+&gt; = tablex.filter(Gt(_1,<span class="number">0</span>), {<span class="number">1</span>,-<span class="number">1</span>,<span class="number">2</span>,<span class="number">4</span>,-<span class="number">3</span>})
+{<span class="number">1</span>,<span class="number">2</span>,<span class="number">4</span>}
+</pre>
+
+
+<p>It is useful to express the fact that a function returns multiple values. For
+instance, <a href="../libraries/pl.tablex.html#pairmap">tablex.pairmap</a> expects a function that will be called with the key
+and the value, and returns the new value and the key, in that order.</p>
+
+<pre>
+&gt; = pairmap(Args(_2,_1:upper()),{fred=<span class="number">1</span>,alice=<span class="number">2</span>})
+{ALICE=<span class="number">2</span>,FRED=<span class="number">1</span>}
+</pre>
+
+
+<p>PEs cannot contain <code>nil</code> values, since PE function arguments are represented as
+an array. Instead, a special value called <code>Nil</code> is provided. So say
+<code>_1:f(Nil,1)</code> instead of <code>_1:f(nil,1)</code>.</p>
+
+<p>A placeholder expression cannot be automatically used as a Lua function. The
+technical reason is that the call operator must be overloaded to construct
+function calls like <code>_1(1)</code>. If you want to force a PE to return a function, use
+<a href="../libraries/pl.func.html#I">func.I</a>.</p>
+
+<pre>
+&gt; = tablex.map(_1(<span class="number">10</span>),{I(<span class="number">2</span>*_1),I(_1*_1),I(_1+<span class="number">2</span>)})
+{<span class="number">20</span>,<span class="number">100</span>,<span class="number">12</span>}
+</pre>
+
+
+<p>Here we make a table of functions taking a single argument, and then call them
+all with a value of 10.</p>
+
+<p>The essential idea with PEs is to &lsquo;quote&rsquo; an expression so that it is not
+immediately evaluated, but instead turned into a function that can be applied
+later to some arguments. The basic mechanism is to wrap values and placeholders
+so that the usual Lua operators have the effect of building up an <em>expression
+tree</em>. (It turns out that you can do <em>symbolic algebra</em> using PEs, see
+<a href="../examples/symbols.lua.html#">symbols.lua</a> in the examples directory, and its test runner <code>testsym.lua</code>, which
+demonstrates symbolic differentiation.)</p>
+
+<p>The rule is that if any operator has a PE operand, the result will be quoted.
+Sometimes we need to quote things explicitly. For instance, say we want to pass a
+function to a filter that must return true if the element value is in a set.
+<code>set[_1]</code> is the obvious expression, but it does not give the desired result,
+since it evaluates directly, giving <code>nil</code>. Indexing works differently than a
+binary operation like addition (set+<em>1 </em>is_ properly quoted) so there is a need
+for an explicit quoting or wrapping operation. This is the job of the <code>_</code>
+function; the PE in this case should be <code>_(set)[_1]</code>. This works for functions
+as well, as a convenient alternative to registering functions: <code>_(math.sin)(_1)</code>.
+This is equivalent to using the `lines' method:</p>
+
+<pre>
+<span class="keyword">for</span> line <span class="keyword">in</span> I(_(f):read()) <span class="keyword">do</span> <span class="global">print</span>(line) <span class="keyword">end</span>
+</pre>
+
+
+<p>Now this will work for <em>any</em> &lsquo;file-like&rsquo; object which which has a <code>read</code> method
+returning the next line. If you had a LuaSocket client which was being &lsquo;pushed&rsquo;
+by lines sent from a server, then <code>_(s):receive &apos;*l&apos;</code> would create an iterator
+for accepting input. These forms can be convenient for adapting your data flow so
+that it can be passed to the sequence functions in `pl.seq'.</p>
+
+<p>Placeholder expressions can be mixed with sequence wrapper expressions.
+<a href="../libraries/pl.lexer.html#lua">lexer.lua</a> will give us a double-valued sequence of tokens, where the first
+value is a type, and the second is a value. We filter out only the values where
+the type is &lsquo;iden&rsquo;, extract the actual value using <code>map</code>, get the unique values
+and finally copy to a list.</p>
+
+<pre>
+&gt; str = <span class="string">'for i=1,10 do for j = 1,10 do print(i,j) end end'</span>
+&gt; = seq(lexer.lua(str)):filter(<span class="string">'=='</span>,<span class="string">'iden'</span>):map(_2):unique():copy()
+{i,<span class="global">print</span>,j}
+</pre>
+
+
+<p>This is a particularly intense line (and I don&rsquo;t always suggest making everything
+a one-liner!); the key is the behaviour of <code>map</code>, which will take both values of
+the sequence, so <code>_2</code> returns the value part. (Since <code>filter</code> here takes extra
+arguments, it only operates on the type values.)</p>
+
+<p>There are some performance considerations to using placeholder expressions.
+Instantiating a PE requires constructing and compiling a function, which is not
+such a fast operation. So to get best performance, factor out PEs from loops like
+this;</p>
+
+<pre>
+<span class="keyword">local</span> fn = I(_1:f() + _2:g())
+<span class="keyword">for</span> i = <span class="number">1</span>,n <span class="keyword">do</span>
+ res[i] = tablex.map2(fn,first[i],second[i])
+<span class="keyword">end</span>
+</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/08-additional.md.html b/docs/manual/08-additional.md.html
new file mode 100644
index 0000000..4e7cfc5
--- /dev/null
+++ b/docs/manual/08-additional.md.html
@@ -0,0 +1,816 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Simple_Input_Patterns">Simple Input Patterns </a></li>
+<li><a href="#Command_line_Programs_with_Lapp">Command-line Programs with Lapp </a></li>
+<li><a href="#Simple_Test_Framework">Simple Test Framework </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><strong>Additional Libraries</strong></li>
+ <li><a href="../manual/09-discussion.md.html">Technical Choices</a></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Additional Libraries</h2>
+
+<p>Libraries in this section are no longer considered to be part of the Penlight
+core, but still provide specialized functionality when needed.</p>
+
+<p><a id="sip"/></p>
+
+<p><a name="Simple_Input_Patterns"></a></p>
+
+<h3>Simple Input Patterns</h3>
+
+<p>Lua string pattern matching is very powerful, and usually you will not need a
+traditional regular expression library. Even so, sometimes Lua code ends up
+looking like Perl, which happens because string patterns are not always the
+easiest things to read, especially for the casual reader. Here is a program
+which needs to understand three distinct date formats:</p>
+
+<pre>
+<span class="comment">-- parsing dates using Lua string patterns
+</span>months={Jan=<span class="number">1</span>,Feb=<span class="number">2</span>,Mar=<span class="number">3</span>,Apr=<span class="number">4</span>,May=<span class="number">5</span>,Jun=<span class="number">6</span>,
+Jul=<span class="number">7</span>,Aug=<span class="number">8</span>,Sep=<span class="number">9</span>,Oct=<span class="number">10</span>,Nov=<span class="number">11</span>,Dec=<span class="number">12</span>}
+
+<span class="keyword">function</span> check_and_process(d,m,y)
+ d = <span class="global">tonumber</span>(d)
+ m = <span class="global">tonumber</span>(m)
+ y = <span class="global">tonumber</span>(y)
+ ....
+<span class="keyword">end</span>
+
+<span class="keyword">for</span> line <span class="keyword">in</span> f:lines() <span class="keyword">do</span>
+ <span class="comment">-- ordinary (English) date format
+</span> <span class="keyword">local</span> d,m,y = line:match(<span class="string">'(%d+)/(%d+)/(%d+)'</span>)
+ <span class="keyword">if</span> d <span class="keyword">then</span>
+ check_and_process(d,m,y)
+ <span class="keyword">else</span> <span class="comment">-- ISO date??
+</span> y,m,d = line:match(<span class="string">'(%d+)%-(%d+)%-(%d+)'</span>)
+ <span class="keyword">if</span> y <span class="keyword">then</span>
+ check_and_process(d,m,y)
+ <span class="keyword">else</span> <span class="comment">-- &lt;day&gt; &lt;month-name&gt; &lt;year&gt;?
+</span> d,mm,y = line:match(<span class="string">'%(d+)%s+(%a+)%s+(%d+)'</span>)
+ m = months[mm]
+ check_and_process(d,m,y)
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p>These aren&rsquo;t particularly difficult patterns, but already typical issues are
+appearing, such as having to escape &lsquo;-&rsquo;. Also, <a href="https://www.lua.org/manual/5.1/manual.html#pdf-string.match">string.match</a> returns its
+captures, so that we&rsquo;re forced to use a slightly awkward nested if-statement.</p>
+
+<p>Verification issues will further cloud the picture, since regular expression
+people try to enforce constraints (like year cannot be more than four digits)
+using regular expressions, on the usual grounds that you shouldn&rsquo;t stop using a
+hammer when you are enjoying yourself.</p>
+
+<p><a href="../libraries/pl.sip.html#">pl.sip</a> provides a simple, intuitive way to detect patterns in strings and
+extract relevant parts.</p>
+
+<pre>
+&gt; sip = <span class="global">require</span> <span class="string">'pl.sip'</span>
+&gt; dump = <span class="global">require</span>(<span class="string">'pl.pretty'</span>).dump
+&gt; res = {}
+&gt; c = sip.compile <span class="string">'ref=$S{file}:$d{line}'</span>
+&gt; = c(<span class="string">'ref=hello.c:10'</span>,res)
+<span class="keyword">true</span>
+&gt; dump(res)
+{
+ line = <span class="number">10</span>,
+ file = <span class="string">"hello.c"</span>
+}
+&gt; = c(<span class="string">'ref=long name, no line'</span>,res)
+<span class="keyword">false</span>
+</pre>
+
+
+<p><a href="../libraries/pl.sip.html#compile">sip.compile</a> creates a pattern matcher function, which takes a string and a
+table as arguments. If the string matches the pattern, then <code>true</code> is returned
+and the table is populated according to the captures within the pattern.</p>
+
+<p>Here is another version of the date parser:</p>
+
+<pre>
+<span class="comment">-- using SIP patterns
+</span><span class="keyword">function</span> check(t)
+ check_and_process(t.day,t.month,t.year)
+<span class="keyword">end</span>
+
+shortdate = sip.compile(<span class="string">'$d{day}/$d{month}/$d{year}'</span>)
+longdate = sip.compile(<span class="string">'$d{day} $v{mon} $d{year}'</span>)
+isodate = sip.compile(<span class="string">'$d{year}-$d{month}-$d{day}'</span>)
+
+<span class="keyword">for</span> line <span class="keyword">in</span> f:lines() <span class="keyword">do</span>
+ <span class="keyword">local</span> res = {}
+ <span class="keyword">if</span> shortdate(str,res) <span class="keyword">then</span>
+ check(res)
+ <span class="keyword">elseif</span> isodate(str,res) <span class="keyword">then</span>
+ check(res)
+ <span class="keyword">elseif</span> longdate(str,res) <span class="keyword">then</span>
+ res.month = months[res.mon]
+ check(res)
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p>SIP captures start with &lsquo;$&rsquo;, then a one-character type, and then an
+optional variable name in curly braces.</p>
+
+<pre>
+Type Meaning
+v identifier
+i possibly signed integer
+f floating-point number
+r rest of line
+q quoted <span class="global">string</span> (quoted using either ' <span class="keyword">or</span> ")
+p a path name
+( anything inside balanced parentheses
+[ anything inside balanced brackets
+{ anything inside balanced curly brackets
+&lt; anything inside balanced angle brackets
+</pre>
+
+
+<p>If a type is not one of the above, then it&rsquo;s assumed to be one of the standard
+Lua character classes, and will match one or more repetitions of that class.
+Any spaces you leave in your pattern will match any number of spaces, including
+zero, unless the spaces are between two identifier characters or patterns
+matching them; in that case, at least one space will be matched.</p>
+
+<p>SIP captures (like <code>$v{mon}</code>) do not have to be named. You can use just <code>$v</code>, but
+you have to be consistent; if a pattern contains unnamed captures, then all
+captures must be unnamed. In this case, the result table is a simple list of
+values.</p>
+
+<p><a href="../libraries/pl.sip.html#match">sip.match</a> is a useful shortcut if you want to compile and match in one call,
+without saving the compiled pattern. It caches the result, so it is not much
+slower than explicitly using <a href="../libraries/pl.sip.html#compile">sip.compile</a>.</p>
+
+<pre>
+&gt; sip.match(<span class="string">'($q{first},$q{second})'</span>,<span class="string">'("john","smith")'</span>,res)
+<span class="keyword">true</span>
+&gt; res
+{second=<span class="string">'smith'</span>,first=<span class="string">'john'</span>}
+&gt; res = {}
+&gt; sip.match(<span class="string">'($q,$q)'</span>,<span class="string">'("jan","smit")'</span>,res) <span class="comment">-- unnamed captures
+</span><span class="keyword">true</span>
+&gt; res
+{<span class="string">'jan'</span>,<span class="string">'smit'</span>}
+&gt; sip.match(<span class="string">'($q,$q)'</span>,<span class="string">'("jan", "smit")'</span>,res)
+<span class="keyword">false</span> <span class="comment">---&gt; oops! Can't handle extra space!
+</span>&gt; sip.match(<span class="string">'( $q , $q )'</span>,<span class="string">'("jan", "smit")'</span>,res)
+<span class="keyword">true</span>
+</pre>
+
+
+<p>As a general rule, allow for whitespace in your patterns.</p>
+
+<p>Finally, putting a &lsquo;$&rsquo; at the end of a pattern means &lsquo;capture the rest of the
+line, starting at the first non-space&rsquo;. It is a shortcut for &lsquo;$r{rest}&rsquo;,
+or just &lsquo;$r&rsquo; if no named captures are used.</p>
+
+<pre>
+&gt; sip.match(<span class="string">'( $q , $q ) $'</span>,<span class="string">'("jan", "smit") and a string'</span>,res)
+<span class="keyword">true</span>
+&gt; res
+{<span class="string">'jan'</span>,<span class="string">'smit'</span>,<span class="string">'and a string'</span>}
+&gt; res = {}
+&gt; sip.match(<span class="string">'( $q{first} , $q{last} ) $'</span>,<span class="string">'("jan", "smit") and a string'</span>,res)
+<span class="keyword">true</span>
+&gt; res
+{first=<span class="string">'jan'</span>,rest=<span class="string">'and a string'</span>,last=<span class="string">'smit'</span>}
+</pre>
+
+
+<p><a id="lapp"/></p>
+
+<p><a name="Command_line_Programs_with_Lapp"></a></p>
+
+<h3>Command-line Programs with Lapp</h3>
+
+<p><a href="../libraries/pl.lapp.html#">pl.lapp</a> is a small and focused Lua module which aims to make standard
+command-line parsing easier and intuitive. It implements the standard GNU style,
+i.e. short flags with one letter start with &lsquo;-&rsquo;, and there may be an additional
+long flag which starts with &lsquo;&ndash;&rsquo;. Generally options which take an argument expect
+to find it as the next parameter (e.g. &lsquo;gcc test.c -o test&rsquo;) but single short
+options taking a value can dispense with the space (e.g. &lsquo;head -n4
+test.c&rsquo; or <code>gcc -I/usr/include/lua/5.1 &hellip;</code>)</p>
+
+<p>As far as possible, Lapp will convert parameters into their equivalent Lua types,
+i.e. convert numbers and convert filenames into file objects. If any conversion
+fails, or a required parameter is missing, an error will be issued and the usage
+text will be written out. So there are two necessary tasks, supplying the flag
+and option names and associating them with a type.</p>
+
+<p>For any non-trivial script, even for personal consumption, it&rsquo;s necessary to
+supply usage text. The novelty of Lapp is that it starts from that point and
+defines a loose format for usage strings which can specify the names and types of
+the parameters.</p>
+
+<p>An example will make this clearer:</p>
+
+<pre>
+<span class="comment">-- scale.lua
+</span> lapp = <span class="global">require</span> <span class="string">'pl.lapp'</span>
+ <span class="keyword">local</span> args = lapp <span class="string">[[
+ Does some calculations
+ -o,--offset (default 0.0) Offset to add to scaled number
+ -s,--scale (number) Scaling factor
+ &lt;number&gt; (number) Number to be scaled
+ ]]</span>
+
+ <span class="global">print</span>(args.offset + args.scale * args.number)
+</pre>
+
+
+<p>Here is a command-line session using this script:</p>
+
+<pre>
+$ lua scale.lua
+scale.lua:missing required parameter: scale
+
+Does some calculations
+ -o,<span class="comment">--offset (default 0.0) Offset to add to scaled number
+</span> -s,<span class="comment">--scale (number) Scaling factor
+</span> &lt;number&gt; (number ) Number to be scaled
+
+$ lua scale.lua -s <span class="number">2.2</span> <span class="number">10</span>
+<span class="number">22</span>
+
+$ lua scale.lua -s <span class="number">2.2</span> x10
+scale.lua:unable to convert to number: x10
+
+....(usage as before)
+</pre>
+
+
+<p>There are two kinds of lines in Lapp usage strings which are meaningful; option
+and parameter lines. An option line gives the short option, optionally followed
+by the corresponding long option. A type specifier in parentheses may follow.
+Similarly, a parameter line starts with &lsquo;<NAME>&rsquo;, followed by a type
+specifier.</p>
+
+<p>Type specifiers usually start with a type name: one of &lsquo;boolean&rsquo;, &lsquo;string&rsquo;,&lsquo;number&rsquo;,&lsquo;file-in&rsquo; or
+&lsquo;file-out&rsquo;. You may leave this out, but then <em>must</em> say &lsquo;default&rsquo; followed by a value.
+If a flag or parameter has a default, it is not <em>required</em> and is set to the default. The actual
+type is deduced from this value (number, string, file or boolean) if not provided directly.
+&lsquo;Deduce&rsquo; is a fancy word for &lsquo;guess&rsquo; and it can be wrong, e.g &lsquo;(default 1)&rsquo;
+will always be a number. You can say &lsquo;(string default 1)&rsquo; to override the guess.
+There are file values for the predefined console streams: stdin, stdout, stderr.</p>
+
+<p>The boolean type is the default for flags. Not providing the type specifier is equivalent to
+&lsquo;(boolean default false)<code>. If the flag is meant to be 'turned off' then either the full
+'(boolean default true)</code> or the shortcut &rsquo;(default true)&lsquo; will work.</p>
+
+<p>An alternative to <code>default</code> is <code>optional</code>:</p>
+
+<pre>
+<span class="keyword">local</span> lapp = <span class="global">require</span> <span class="string">'pl.lapp'</span>
+<span class="keyword">local</span> args = lapp <span class="string">[[
+ --cmd (optional string) Command to run.
+]]</span>
+
+<span class="keyword">if</span> args.cmd <span class="keyword">then</span>
+ <span class="global">os</span>.execute(args.cmd)
+<span class="keyword">end</span>
+</pre>
+
+
+<p>Here we&rsquo;re implying that <code>cmd</code> need not be specified (just as with <code>default</code>) but if not
+present, then <code>args.cmd</code> is <code>nil</code>, which will always test false.</p>
+
+<p>The rest of the line is ignored and can be used for explanatory text.</p>
+
+<p>This script shows the relation between the specified parameter names and the
+fields in the output table.</p>
+
+<pre>
+<span class="comment">-- simple.lua
+</span><span class="keyword">local</span> args = <span class="global">require</span> (<span class="string">'pl.lapp'</span>) <span class="string">[[
+Various flags and option types
+ -p A simple optional flag, defaults to false
+ -q,--quiet A simple flag with long name
+ -o (string) A required option with argument
+ -s (default 'save') Optional string with default 'save' (single quotes ignored)
+ -n (default 1) Optional numerical flag with default 1
+ -b (string default 1) Optional string flag with default '1' (type explicit)
+ &lt;input&gt; (default stdin) Optional input file parameter, reads from stdin
+]]</span>
+
+<span class="keyword">for</span> k,v <span class="keyword">in</span> <span class="global">pairs</span>(args) <span class="keyword">do</span>
+ <span class="global">print</span>(k,v)
+<span class="keyword">end</span>
+</pre>
+
+
+<p>I&rsquo;ve just dumped out all values of the args table; note that args.quiet has
+become true, because it&rsquo;s specified; args.p defaults to false. If there is a long
+name for an option, that will be used in preference as a field name. A type or
+default specifier is not necessary for simple flags, since the default type is
+boolean.</p>
+
+<pre>
+$ simple -o test -q simple.lua
+p <span class="keyword">false</span>
+input file (<span class="number">781</span>C1BD8)
+quiet <span class="keyword">true</span>
+o test
+input_name simple.lua
+D:\dev\lua\lapp&gt;simple -o test simple.lua one two three
+<span class="number">1</span> one
+<span class="number">2</span> two
+<span class="number">3</span> three
+p <span class="keyword">false</span>
+quiet <span class="keyword">false</span>
+input file (<span class="number">781</span>C1BD8)
+o test
+input_name simple.lua
+</pre>
+
+
+<p>The parameter input has been set to an open read-only file object - we know it
+must be a read-only file since that is the type of the default value. The field
+input_name is automatically generated, since it&rsquo;s often useful to have access to
+the original filename.</p>
+
+<p>Notice that any extra parameters supplied will be put in the result table with
+integer indices, i.e. args[i] where i goes from 1 to #args.</p>
+
+<p>Files don&rsquo;t really have to be closed explicitly for short scripts with a quick
+well-defined mission, since the result of garbage-collecting file objects is to
+close them.</p>
+
+<h4>Enforcing a Range and Enumerations</h4>
+
+<p>The type specifier can also be of the form &lsquo;(&rsquo; MIN &lsquo;..&rsquo; MAX &lsquo;)&rsquo; or a set of strings
+separated by &lsquo;|&rsquo;.</p>
+
+<pre>
+<span class="keyword">local</span> lapp = <span class="global">require</span> <span class="string">'pl.lapp'</span>
+<span class="keyword">local</span> args = lapp <span class="string">[[
+ Setting ranges
+ &lt;x&gt; (1..10) A number from 1 to 10
+ &lt;y&gt; (-5..1e6) Bigger range
+ &lt;z&gt; (slow|medium|fast)
+]]</span>
+
+<span class="global">print</span>(args.x,args.y)
+</pre>
+
+
+<p>Here the meaning of ranges is that the value is greater or equal to MIN and less or equal
+to MAX.
+An &lsquo;enum&rsquo; is a <em>string</em> that can only have values from a specified set.</p>
+
+<h4>Custom Types</h4>
+
+<p>There is no builti-in way to force a parameter to be a whole number, but
+you may define a custom type that does this:</p>
+
+<pre>
+lapp = <span class="global">require</span> (<span class="string">'pl.lapp'</span>)
+
+lapp.add_type(<span class="string">'integer'</span>,<span class="string">'number'</span>,
+ <span class="keyword">function</span>(x)
+ lapp.<span class="global">assert</span>(<span class="global">math</span>.ceil(x) == x, <span class="string">'not an integer!'</span>)
+ <span class="keyword">end</span>
+)
+
+<span class="keyword">local</span> args = lapp <span class="string">[[
+ &lt;ival&gt; (integer) Process PID
+]]</span>
+
+<span class="global">print</span>(args.ival)
+</pre>
+
+
+<p><a href="../libraries/pl.lapp.html#add_type">lapp.add_type</a> takes three parameters, a type name, a converter and a constraint
+function. The constraint function is expected to throw an assertion if some
+condition is not true; we use <a href="../libraries/pl.lapp.html#assert">lapp.assert</a> because it fails in the standard way
+for a command-line script. The converter argument can either be a type name known
+to Lapp, or a function which takes a string and generates a value.</p>
+
+<p>Here&rsquo;s a useful custom type that allows dates to be input as <a href="../classes/pl.Date.html#">pl.Date</a> values:</p>
+
+<pre>
+<span class="keyword">local</span> df = Date.Format()
+
+lapp.add_type(<span class="string">'date'</span>,
+ <span class="keyword">function</span>(s)
+ <span class="keyword">local</span> d,e = df:parse(s)
+ lapp.<span class="global">assert</span>(d,e)
+ <span class="keyword">return</span> d
+ <span class="keyword">end</span>
+)
+</pre>
+
+
+<h4>&lsquo;varargs&rsquo; Parameter Arrays</h4>
+
+<pre>
+lapp = <span class="global">require</span> <span class="string">'pl.lapp'</span>
+<span class="keyword">local</span> args = lapp <span class="string">[[
+Summing numbers
+ &lt;numbers...&gt; (number) A list of numbers to be summed
+]]</span>
+
+<span class="keyword">local</span> sum = <span class="number">0</span>
+<span class="keyword">for</span> i,x <span class="keyword">in</span> <span class="global">ipairs</span>(args.numbers) <span class="keyword">do</span>
+ sum = sum + x
+<span class="keyword">end</span>
+<span class="global">print</span> (<span class="string">'sum is '</span>..sum)
+</pre>
+
+
+<p>The parameter number has a trailing &lsquo;&hellip;&rsquo;, which indicates that this parameter is
+a &lsquo;varargs&rsquo; parameter. It must be the last parameter, and args.number will be an
+array.</p>
+
+<p>Consider this implementation of the head utility from Mac OS X:</p>
+
+<pre>
+<span class="comment">-- implements a BSD-style head
+</span><span class="comment">-- (see http://www.manpagez.com/man/1/head/osx-10.3.php)
+</span>
+lapp = <span class="global">require</span> (<span class="string">'pl.lapp'</span>)
+
+<span class="keyword">local</span> args = lapp <span class="string">[[
+Print the first few lines of specified files
+ -n (default 10) Number of lines to print
+ &lt;files...&gt; (default stdin) Files to print
+]]</span>
+
+<span class="comment">-- by default, lapp converts file arguments to an actual Lua file object.
+</span><span class="comment">-- But the actual filename is always available as &lt;file&gt;_name.
+</span><span class="comment">-- In this case, 'files' is a varargs array, so that 'files_name' is
+</span><span class="comment">-- also an array.
+</span><span class="keyword">local</span> nline = args.n
+<span class="keyword">local</span> nfile = #args.files
+<span class="keyword">for</span> i = <span class="number">1</span>,nfile <span class="keyword">do</span>
+ <span class="keyword">local</span> file = args.files[i]
+ <span class="keyword">if</span> nfile &gt; <span class="number">1</span> <span class="keyword">then</span>
+ <span class="global">print</span>(<span class="string">'==&gt; '</span>..args.files_name[i]..<span class="string">' &lt;=='</span>)
+ <span class="keyword">end</span>
+ <span class="keyword">local</span> n = <span class="number">0</span>
+ <span class="keyword">for</span> line <span class="keyword">in</span> file:lines() <span class="keyword">do</span>
+ <span class="global">print</span>(line)
+ n = n + <span class="number">1</span>
+ <span class="keyword">if</span> n == nline <span class="keyword">then</span> <span class="keyword">break</span> <span class="keyword">end</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span>
+</pre>
+
+
+<p>Note how we have access to all the filenames, because the auto-generated field
+<code>files_name</code> is also an array!</p>
+
+<p>(This is probably not a very considerate script, since Lapp will open all the
+files provided, and only close them at the end of the script. See the <code>xhead.lua</code>
+example for another implementation.)</p>
+
+<p>Flags and options may also be declared as vararg arrays, and can occur anywhere.
+If there is both a short and long form, then the trailing &ldquo;&hellip;&rdquo; must happen after the long form,
+for example &ldquo;-x,&ndash;network&hellip; (string)&hellip;&rdquo;,</p>
+
+<p>Bear in mind that short options can be combined (like &lsquo;tar -xzf&rsquo;), so it&rsquo;s
+perfectly legal to have &lsquo;-vvv&rsquo;. But normally the value of args.v is just a simple
+<code>true</code> value.</p>
+
+<pre>
+<span class="keyword">local</span> args = <span class="global">require</span> (<span class="string">'pl.lapp'</span>) <span class="string">[[
+ -v... Verbosity level; can be -v, -vv or -vvv
+]]</span>
+vlevel = <span class="keyword">not</span> args.v[<span class="number">1</span>] <span class="keyword">and</span> <span class="number">0</span> <span class="keyword">or</span> #args.v
+<span class="global">print</span>(vlevel)
+</pre>
+
+
+<p>The vlevel assigment is a bit of Lua voodoo, so consider the cases:</p>
+
+<pre>
+* No -v flag, v is just { <span class="keyword">false</span> }
+* One -v flags, v is { <span class="keyword">true</span> }
+* Two -v flags, v is { <span class="keyword">true</span>, <span class="keyword">true</span> }
+* Three -v flags, v is { <span class="keyword">true</span>, <span class="keyword">true</span>, <span class="keyword">true</span> }
+</pre>
+
+
+<h4>Defining a Parameter Callback</h4>
+
+<p>If a script implements <code>lapp.callback</code>, then Lapp will call it after each
+argument is parsed. The callback is passed the parameter name, the raw unparsed
+value, and the result table. It is called immediately after assignment of the
+value, so the corresponding field is available.</p>
+
+<pre>
+lapp = <span class="global">require</span> (<span class="string">'pl.lapp'</span>)
+
+<span class="keyword">function</span> lapp.callback(parm,arg,args)
+ <span class="global">print</span>(<span class="string">'+'</span>,parm,arg)
+<span class="keyword">end</span>
+
+<span class="keyword">local</span> args = lapp <span class="string">[[
+Testing parameter handling
+ -p Plain flag (defaults to false)
+ -q,--quiet Plain flag with GNU-style optional long name
+ -o (string) Required string option
+ -n (number) Required number option
+ -s (default 1.0) Option that takes a number, but will default
+ &lt;start&gt; (number) Required number argument
+ &lt;input&gt; (default stdin) A parameter which is an input file
+ &lt;output&gt; (default stdout) One that is an output file
+]]</span>
+<span class="global">print</span> <span class="string">'args'</span>
+<span class="keyword">for</span> k,v <span class="keyword">in</span> <span class="global">pairs</span>(args) <span class="keyword">do</span>
+ <span class="global">print</span>(k,v)
+<span class="keyword">end</span>
+</pre>
+
+
+<p>This produces the following output:</p>
+
+<pre>
+$ args -o name -n <span class="number">2</span> <span class="number">10</span> args.lua
++ o name
++ n <span class="number">2</span>
++ start <span class="number">10</span>
++ input args.lua
+args
+p <span class="keyword">false</span>
+s <span class="number">1</span>
+input_name args.lua
+quiet <span class="keyword">false</span>
+output file (<span class="number">781</span>C1B98)
+start <span class="number">10</span>
+input file (<span class="number">781</span>C1BD8)
+o name
+n <span class="number">2</span>
+</pre>
+
+
+<p>Callbacks are needed when you want to take action immediately on parsing an
+argument.</p>
+
+<h4>Slack Mode</h4>
+
+<p>If you&rsquo;d like to use a multi-letter &lsquo;short&rsquo; parameter you need to set
+the <code>lapp.slack</code> variable to <code>true</code>.</p>
+
+<p>In the following example we also see how default <code>false</code> and default <code>true</code> flags can be used
+and how to overwrite the default <code>-h</code> help flag (<code>&ndash;help</code> still works fine) - this applies
+to non-slack mode as well.</p>
+
+<pre>
+<span class="comment">-- Parsing the command line ----------------------------------------------------
+</span><span class="comment">-- test.lua
+</span><span class="keyword">local</span> lapp = <span class="global">require</span> <span class="string">'pl.lapp'</span>
+<span class="keyword">local</span> pretty = <span class="global">require</span> <span class="string">'pl.pretty'</span>
+lapp.slack = <span class="keyword">true</span>
+<span class="keyword">local</span> args = lapp <span class="string">[[
+Does some calculations
+ -v, --video (string) Specify input video
+ -w, --width (default 256) Width of the video
+ -h, --height (default 144) Height of the video
+ -t, --time (default 10) Seconds of video to process
+ -sk,--seek (default 0) Seek number of seconds
+ -f1,--flag1 A false flag
+ -f2,--flag2 A false flag
+ -f3,--flag3 (default true) A true flag
+ -f4,--flag4 (default true) A true flag
+]]</span>
+
+pretty.dump(args)
+</pre>
+
+
+<p>And here we can see the output of <code>test.lua</code>:</p>
+
+<pre>
+$&gt; lua test.lua -v abc <span class="comment">--time 40 -h 20 -sk 15 --flag1 -f3
+</span><span class="comment">----&gt;
+</span>{
+ width = <span class="number">256</span>,
+ flag1 = <span class="keyword">true</span>,
+ flag3 = <span class="keyword">false</span>,
+ seek = <span class="number">15</span>,
+ flag2 = <span class="keyword">false</span>,
+ video = abc,
+ time = <span class="number">40</span>,
+ height = <span class="number">20</span>,
+ flag4 = <span class="keyword">true</span>
+}
+</pre>
+
+
+<p><a name="Simple_Test_Framework"></a></p>
+
+<h3>Simple Test Framework</h3>
+
+<p><a href="../libraries/pl.test.html#">pl.test</a> was originally developed for the sole purpose of testing Penlight itself,
+but you may find it useful for your own applications. (<a href="http://lua-users.org/wiki/UnitTesting">There are many other options</a>.)</p>
+
+<p>Most of the goodness is in <a href="../libraries/pl.test.html#asserteq">test.asserteq</a>. It uses <a href="../libraries/pl.tablex.html#deepcompare">tablex.deepcompare</a> on its two arguments,
+and by default quits the test application with a non-zero exit code, and an informative
+message printed to stderr:</p>
+
+<pre>
+<span class="keyword">local</span> test = <span class="global">require</span> <span class="string">'pl.test'</span>
+
+test.asserteq({<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>},{<span class="number">10</span>,<span class="number">20</span>,<span class="number">30.1</span>})
+
+<span class="comment">--~ test-test.lua:3: assertion failed
+</span><span class="comment">--~ got: {
+</span><span class="comment">--~ [1] = 10,
+</span><span class="comment">--~ [2] = 20,
+</span><span class="comment">--~ [3] = 30
+</span><span class="comment">--~ }
+</span><span class="comment">--~ needed: {
+</span><span class="comment">--~ [1] = 10,
+</span><span class="comment">--~ [2] = 20,
+</span><span class="comment">--~ [3] = 30.1
+</span><span class="comment">--~ }
+</span><span class="comment">--~ these values were not equal</span>
+</pre>
+
+
+<p>This covers most cases but it&rsquo;s also useful to compare strings using <a href="https://www.lua.org/manual/5.1/manual.html#pdf-string.match">string.match</a></p>
+
+<pre>
+<span class="comment">-- must start with bonzo the dog
+</span>test.assertmatch (<span class="string">'bonzo the dog is here'</span>,<span class="string">'^bonzo the dog'</span>)
+<span class="comment">-- must end with an integer
+</span>test.assertmatch (<span class="string">'hello 42'</span>,<span class="string">'%d+$'</span>)
+</pre>
+
+
+<p>Since Lua errors are usually strings, this matching strategy is used to test &lsquo;exceptions&rsquo;:</p>
+
+<pre>
+test.assertraise(<span class="keyword">function</span>()
+ <span class="keyword">local</span> t = <span class="keyword">nil</span>
+ <span class="global">print</span>(t.bonzo)
+<span class="keyword">end</span>,<span class="string">'nil value'</span>)
+</pre>
+
+
+<p>(Some care is needed to match the essential part of the thrown error if you care
+for portability, since in Lua 5.2
+the exact error is &ldquo;attempt to index local &rsquo;t' (a nil value)&rdquo; and in Lua 5.3 the error
+is &ldquo;attempt to index a nil value (local &rsquo;t')&rdquo;)</p>
+
+<p>There is an extra optional argument to these test functions, which is helpful when writing
+test helper functions. There you want to highlight the failed line, not the actual call
+to <code>asserteq</code> or <code>assertmatch</code> - line 33 here is the call to <code>is_iden</code></p>
+
+<pre>
+<span class="keyword">function</span> is_iden(str)
+ test.assertmatch(str,<span class="string">'^[%a_][%w_]*$'</span>,<span class="number">1</span>)
+<span class="keyword">end</span>
+
+is_iden <span class="string">'alpha_dog'</span>
+is_iden <span class="string">'$dollars'</span>
+
+<span class="comment">--~ test-test.lua:33: assertion failed
+</span><span class="comment">--~ got: "$dollars"
+</span><span class="comment">--~ needed: "^[%a_][%w_]*$"
+</span><span class="comment">--~ these strings did not match</span>
+</pre>
+
+
+<p>Useful Lua functions often return multiple values, and <a href="../libraries/pl.test.html#tuple">test.tuple</a> is a convenient way to
+capture these values, whether they contain nils or not.</p>
+
+<pre>
+T = test.tuple
+
+<span class="comment">--- common error pattern
+</span><span class="keyword">function</span> failing()
+ <span class="keyword">return</span> <span class="keyword">nil</span>,<span class="string">'failed'</span>
+<span class="keyword">end</span>
+
+test.asserteq(T(failing()),T(<span class="keyword">nil</span>,<span class="string">'failed'</span>))
+</pre>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/docs/manual/09-discussion.md.html b/docs/manual/09-discussion.md.html
new file mode 100644
index 0000000..fa16686
--- /dev/null
+++ b/docs/manual/09-discussion.md.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+ <title>Penlight Documentation</title>
+ <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo"></div>
+ <div id="product_name"><big><b></b></big></div>
+ <div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Penlight</h1>
+
+<ul>
+ <li><a href="../index.html">Index</a></li>
+</ul>
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Modularity_and_Granularity">Modularity and Granularity </a></li>
+<li><a href="#Defining_what_is_Callable">Defining what is Callable </a></li>
+</ul>
+
+
+<h2>Manual</h2>
+<ul class="nowrap">
+ <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
+ <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
+ <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
+ <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
+ <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
+ <li><a href="../manual/06-data.md.html">Data</a></li>
+ <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
+ <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
+ <li><strong>Technical Choices</strong></li>
+</ul>
+<h2>Libraries</h2>
+<ul class="nowrap">
+ <li><a href="../libraries/pl.html">pl</a></li>
+ <li><a href="../libraries/pl.Set.html">pl.Set</a></li>
+ <li><a href="../libraries/pl.app.html">pl.app</a></li>
+ <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
+ <li><a href="../libraries/pl.class.html">pl.class</a></li>
+ <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
+ <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
+ <li><a href="../libraries/pl.config.html">pl.config</a></li>
+ <li><a href="../libraries/pl.data.html">pl.data</a></li>
+ <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
+ <li><a href="../libraries/pl.file.html">pl.file</a></li>
+ <li><a href="../libraries/pl.func.html">pl.func</a></li>
+ <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
+ <li><a href="../libraries/pl.input.html">pl.input</a></li>
+ <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
+ <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
+ <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
+ <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
+ <li><a href="../libraries/pl.path.html">pl.path</a></li>
+ <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
+ <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
+ <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
+ <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
+ <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
+ <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
+ <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
+ <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
+ <li><a href="../libraries/pl.template.html">pl.template</a></li>
+ <li><a href="../libraries/pl.test.html">pl.test</a></li>
+ <li><a href="../libraries/pl.text.html">pl.text</a></li>
+ <li><a href="../libraries/pl.types.html">pl.types</a></li>
+ <li><a href="../libraries/pl.url.html">pl.url</a></li>
+ <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
+ <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
+</ul>
+<h2>Classes</h2>
+<ul class="nowrap">
+ <li><a href="../classes/pl.Date.html">pl.Date</a></li>
+ <li><a href="../classes/pl.List.html">pl.List</a></li>
+ <li><a href="../classes/pl.Map.html">pl.Map</a></li>
+ <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
+ <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
+</ul>
+<h2>Examples</h2>
+<ul class="nowrap">
+ <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
+ <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
+ <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
+ <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
+ <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
+ <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
+ <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
+ <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
+ <li><a href="../examples/testapp.lua.html">testapp.lua</a></li>
+ <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
+ <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
+ <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
+ <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
+ <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
+ <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
+ <li><a href="../examples/which.lua.html">which.lua</a></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+ <h2>Technical Choices</h2>
+
+<p><a name="Modularity_and_Granularity"></a></p>
+
+<h3>Modularity and Granularity</h3>
+
+<p>In an ideal world, a program should only load the libraries it needs. Penlight is
+intended to work in situations where an extra 100Kb of bytecode could be a
+problem. It is straightforward but tedious to load exactly what you need:</p>
+
+<pre>
+<span class="keyword">local</span> data = <span class="global">require</span> <span class="string">'pl.data'</span>
+<span class="keyword">local</span> List = <span class="global">require</span> <span class="string">'pl.List'</span>
+<span class="keyword">local</span> array2d = <span class="global">require</span> <span class="string">'pl.array2d'</span>
+<span class="keyword">local</span> seq = <span class="global">require</span> <span class="string">'pl.seq'</span>
+<span class="keyword">local</span> utils = <span class="global">require</span> <span class="string">'pl.utils'</span>
+</pre>
+
+
+<p>This is the style that I follow in Penlight itself, so that modules don&rsquo;t mess
+with the global environment; also, <code>stringx.import()</code> is not used because it will
+update the global <a href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> table.</p>
+
+<p>But <code>require &apos;pl&apos;</code> is more convenient in scripts; the question is how to ensure
+that one doesn&rsquo;t load the whole kitchen sink as the price of convenience. The
+strategy is to only load modules when they are referenced. In &lsquo;init.lua&rsquo; (which
+is loaded by <code>require &apos;pl&apos;</code>) a metatable is attached to the global table with an
+<code>__index</code> metamethod. Any unknown name is looked up in the list of modules, and
+if found, we require it and make that module globally available. So when
+<a href="../libraries/pl.tablex.html#deepcompare">tablex.deepcompare</a> is encountered, looking up <a href="../libraries/pl.tablex.html#">tablex</a> causes &lsquo;pl.tablex&rsquo; to be
+required. .</p>
+
+<p>Modifying the behaviour of the global table has consequences. For instance, there
+is the famous module <a href="../libraries/pl.strict.html#">strict</a> which comes with Lua itself (perhaps the only
+standard Lua module written in Lua itself) which also does this modification so
+that global variiables must be defined before use. So the implementation in
+&lsquo;init.lua&rsquo; allows for a &lsquo;not found&rsquo; hook, which &lsquo;pl.strict.lua&rsquo; uses. Other
+libraries may install their own metatables for <code>_G</code>, but Penlight will now
+forward any unknown name to the <code>__index</code> defined by the original metatable.</p>
+
+<p>But the strategy is worth the effort: the old &lsquo;kitchen sink&rsquo; &lsquo;init.lua&rsquo; would
+pull in about 260K of bytecode, whereas now typical programs use about 100K less,
+and short scripts even better - for instance, if they were only needing
+functionality in <a href="../libraries/pl.utils.html#">utils</a>.</p>
+
+<p>There are some functions which mark their output table with a special metatable,
+when it seems particularly appropriate. For instance, <a href="../libraries/pl.tablex.html#makeset">tablex.makeset</a> creates a
+<a href="../libraries/pl.Set.html#">Set</a>, and <a href="../libraries/pl.seq.html#copy">seq.copy</a> creates a <a href="../classes/pl.List.html#">List</a>. But this does not automatically result in
+the loading of <a href="../libraries/pl.Set.html#">pl.Set</a> and <a href="../classes/pl.List.html#">pl.List</a>; only if you try to access any of these
+methods. In &lsquo;utils.lua&rsquo;, there is an exported table called <code>stdmt</code>:</p>
+
+<pre>
+stdmt = { List = {}, Map = {}, Set = {}, MultiMap = {} }
+</pre>
+
+
+<p>If you go through &lsquo;init.lua&rsquo;, then these plain little &lsquo;identity&rsquo; tables get an
+<code>__index</code> metamethod which forces the loading of the full functionality. Here is
+the code from &lsquo;list.lua&rsquo; which starts the ball rolling for lists:</p>
+
+<pre>
+List = utils.stdmt.List
+List.__index = List
+List._name = <span class="string">"List"</span>
+List._class = List
+</pre>
+
+
+<p>The &lsquo;load-on-demand&rsquo; strategy helps to modularize the library. Especially for
+more casual use, <code>require &apos;pl&apos;</code> is a good compromise between convenience and
+modularity.</p>
+
+<p>In this current version, I have generally reduced the amount of trickery
+involved. Previously, <a href="../classes/pl.Map.html#">Map</a> was defined in <a href="../libraries/pl.class.html#">pl.class</a>; now it is sensibly defined
+in <a href="../classes/pl.Map.html#">pl.Map</a>; <a href="../libraries/pl.class.html#">pl.class</a> only contains the basic class mechanism (and returns that
+function.) For consistency, <a href="../classes/pl.List.html#">List</a> is returned directly by <code>require &apos;pl.List&apos;</code>
+(note the uppercase &lsquo;L&rsquo;), Also, the amount of module dependencies in the
+non-core libraries like <a href="../libraries/pl.config.html#">pl.config</a> have been reduced.</p>
+
+<p><a name="Defining_what_is_Callable"></a></p>
+
+<h3>Defining what is Callable</h3>
+
+<p>&lsquo;utils.lua&rsquo; exports <code>function_arg</code> which is used extensively throughout Penlight.
+It defines what is meant by &lsquo;callable&rsquo;. Obviously true functions are immediately
+passed back. But what about strings? The first option is that it represents an
+operator in &lsquo;operator.lua&rsquo;, so that &lsquo;&lt;&rsquo; is just an alias for <a href="../libraries/pl.operator.html#lt">operator.lt</a>.</p>
+
+<p>We then check whether there is a <em>function factory</em> defined for the metatable of
+the value.</p>
+
+<p>(It is true that strings can be made callable, but in practice this turns out to
+be a cute but dubious idea, since <em>all</em> strings share the same metatable. A
+common programming error is to pass the wrong kind of object to a function, and
+it&rsquo;s better to get a nice clean &lsquo;attempting to call a string&rsquo; message rather than
+some obscure trace from the bowels of your library.)</p>
+
+<p>The other module that registers a function factory is <a href="../libraries/pl.func.html#">pl.func</a>. Placeholder
+expressions cannot be directly calleable, and so need to be instantiated and
+cached in as efficient way as possible.</p>
+
+<p>(An inconsistency is that <code>utils.is_callable</code> does not do this thorough check.)</p>
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
+<i style="float:right;">Last updated 2018-11-23 21:07:42 </i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>
diff --git a/doc/manual/01-introduction.md b/docs_topics/01-introduction.md
index a8bf26a..a8bf26a 100644
--- a/doc/manual/01-introduction.md
+++ b/docs_topics/01-introduction.md
diff --git a/doc/manual/02-arrays.md b/docs_topics/02-arrays.md
index 9ee292f..9ee292f 100644
--- a/doc/manual/02-arrays.md
+++ b/docs_topics/02-arrays.md
diff --git a/doc/manual/03-strings.md b/docs_topics/03-strings.md
index 3808175..3808175 100644
--- a/doc/manual/03-strings.md
+++ b/docs_topics/03-strings.md
diff --git a/doc/manual/04-paths.md b/docs_topics/04-paths.md
index 4367fe6..4367fe6 100644
--- a/doc/manual/04-paths.md
+++ b/docs_topics/04-paths.md
diff --git a/doc/manual/05-dates.md b/docs_topics/05-dates.md
index c2431cf..c2431cf 100644
--- a/doc/manual/05-dates.md
+++ b/docs_topics/05-dates.md
diff --git a/doc/manual/06-data.md b/docs_topics/06-data.md
index 8c759d7..8c759d7 100644
--- a/doc/manual/06-data.md
+++ b/docs_topics/06-data.md
diff --git a/doc/manual/07-functional.md b/docs_topics/07-functional.md
index 5921a3d..5921a3d 100644
--- a/doc/manual/07-functional.md
+++ b/docs_topics/07-functional.md
diff --git a/doc/manual/08-additional.md b/docs_topics/08-additional.md
index 2c99497..2c99497 100644
--- a/doc/manual/08-additional.md
+++ b/docs_topics/08-additional.md
diff --git a/doc/manual/09-discussion.md b/docs_topics/09-discussion.md
index 7942d95..7942d95 100644
--- a/doc/manual/09-discussion.md
+++ b/docs_topics/09-discussion.md
diff --git a/lua/pl/utils.lua b/lua/pl/utils.lua
index 2f973ec..9869926 100644
--- a/lua/pl/utils.lua
+++ b/lua/pl/utils.lua
@@ -11,7 +11,7 @@ local append = table.insert
local _unpack = table.unpack -- always injected by 'compat'
local utils = {
- _VERSION = "1.5.4",
+ _VERSION = "1.6.0",
lua51 = compat.lua51,
setfenv = compat.setfenv,
getfenv = compat.getfenv,
diff --git a/penlight-scm-1.rockspec b/penlight-scm-2.rockspec
index 35a834b..b5dbb1c 100644
--- a/penlight-scm-1.rockspec
+++ b/penlight-scm-2.rockspec
@@ -1,5 +1,5 @@
package = "penlight"
-version = "scm-1"
+version = "scm-2"
source = {
url = "git://github.com/stevedonovan/Penlight.git",
@@ -64,5 +64,5 @@ build = {
["pl.types"] = "lua/pl/types.lua",
["pl.import_into"] = "lua/pl/import_into.lua"
},
- copy_directories = {"doc", "tests"}
+ copy_directories = {"docs", "tests"}
}
diff --git a/tests/test-dir.lua b/tests/test-dir.lua
index 6c208e8..a99b7e5 100644
--- a/tests/test-dir.lua
+++ b/tests/test-dir.lua
@@ -20,11 +20,11 @@ asserteq(filtered, {"foobar", "foonbar"})
local normpath = path.normpath
-local doc_files = dir.getfiles(normpath "doc/", "*.ld")
-asserteq(doc_files, {normpath "doc/config.ld"})
+local doc_files = dir.getfiles(normpath "docs/", "*.css")
+asserteq(doc_files, {normpath "docs/ldoc_fixed.css"})
-local all_doc_files = dir.getallfiles(normpath "doc/", "*.ld")
-asserteq(all_doc_files, {normpath "doc/config.ld"})
+local all_doc_files = dir.getallfiles(normpath "docs/", "*.css")
+asserteq(all_doc_files, {normpath "docs/ldoc_fixed.css"})
local test_samples = dir.getallfiles(normpath "tests/lua")
table.sort(test_samples)
diff --git a/tests/test-path.lua b/tests/test-path.lua
index 56e14cc..1f4531b 100644
--- a/tests/test-path.lua
+++ b/tests/test-path.lua
@@ -23,11 +23,11 @@ testpath ([[../../alice/jones]],'../../alice','jones','')
testpath ([[alice]],'','alice','')
testpath ([[/path-to/dog/]],[[/path-to/dog]],'','')
-asserteq( path.isdir( "doc" ), true )
-asserteq( path.isdir( "doc/config.ld" ), false )
+asserteq( path.isdir( "docs" ), true )
+asserteq( path.isdir( "docs/index.html" ), false )
-asserteq( path.isfile( "doc" ), false )
-asserteq( path.isfile( "doc/config.ld" ), true )
+asserteq( path.isfile( "docs" ), false )
+asserteq( path.isfile( "docs/index.html" ), true )
local norm = path.normpath
local p = norm '/a/b'