diff --git a/.gitignore b/.gitignore deleted file mode 100644 index dbac14c..0000000 --- a/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*~ -.DS_Store -/*.src.rock -/Makefile -/build-aux/config.ld -/doc -/lib/std/version.lua -/luacov.*.out -/stdlib-*.tar.gz diff --git a/.luacov b/.luacov deleted file mode 100644 index 40b9d6a..0000000 --- a/.luacov +++ /dev/null @@ -1,52 +0,0 @@ -return { - -- filename to store stats collected - ["statsfile"] = "luacov.stats.out", - - -- filename to store report - ["reportfile"] = "luacov.report.out", - - -- luacov.stats file updating frequency. - -- The lower this value - the more frequenty results will be written out to luacov.stats - -- You may want to reduce this value for short lived scripts (to for example 2) to avoid losing coverage data. - ["savestepsize"] = 100, - - -- Run reporter on completion? (won't work for ticks) - runreport = true, - - -- Delete stats file after reporting? - deletestats = false, - - -- Process Lua code loaded from raw strings - -- (that is, when the 'source' field in the debug info - -- does not start with '@') - codefromstrings = false, - - -- Patterns for files to include when reporting - -- all will be included if nothing is listed - -- (exclude overrules include, do not include - -- the .lua extension, path separator is always '/') - ["include"] = { - "lib/std/_base$", - "lib/std/debug$", - "lib/std/init$", - "lib/std/io$", - "lib/std/math$", - "lib/std/package$", - "lib/std/string$", - "lib/std/table$", - --"lib/std/version$", - }, - - -- Patterns for files to exclude when reporting - -- all will be included if nothing is listed - -- (exclude overrules include, do not include - -- the .lua extension, path separator is always '/') - ["exclude"] = { - "luacov$", - "luacov/reporter$", - "luacov/defaults$", - "luacov/runner$", - "luacov/stats$", - "luacov/tick$", - }, -} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 92f4f73..0000000 --- a/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -language: python - -sudo: false - -env: - matrix: - - LUA="lua=5.3" - - LUA="lua=5.2" - - LUA="lua=5.1" - - LUA="luajit=2.1" - - LUA="luajit=2.0" - -before_install: - - pip install hererocks - - hererocks here -r^ --$LUA --patch - - export PATH=$PWD/here/bin:$PATH - -install: - - luarocks install ldoc - - luarocks install ansicolors - - luarocks install specl - - luarocks install luacov - -script: - - make - - luarocks make - - make check SPECL_OPTS='-vfreport --coverage' - -after_success: - - tail luacov.report.out - - bash <(curl -s https://codecov.io/bash) -v - -notifications: - slack: aspirinc:JyWeNrIdS0J5nf2Pn2BS1cih diff --git a/AUTHORS.md b/AUTHORS.md deleted file mode 100644 index 6589984..0000000 --- a/AUTHORS.md +++ /dev/null @@ -1,27 +0,0 @@ -# Stdlib's contributors - -This file lists major contributors to _stdlib_. If you think you -should be on it, please raise a [github][] issue. Thanks also to all -those who have contributed bug fixes, suggestions and support. - -Gary V. Vaughan now maintains _stdlib_, having rewritten and reorganised -the libraries for hygiene, consistent argument type checking in debug -mode, and object orientation, in addition to adding a lot of new -functionality. - -Reuben Thomas started the standard libraries project, wrote many of the -libraries, and integrated code from other authors. - -John Belmonte helped set the project up on lua-users, and contributed -to the early organisation of the libraries. - -The call trace debugging code is based on test/trace-calls.lua from -the Lua 5.0 distribution. - -Jamie Webb contributed several miscellaneous functions from his -private standard library. - -Johann Hibschman supplied the code on which math.floor and math.round -were based. - -[github]: https://github.com/lua-stdlib/lua-stdlib/issues diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index c2b4620..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (C) 2002-2018 stdlib authors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGE- -MENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index 7b8dd8c..0000000 --- a/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# General Lua Libraries for Lua 5.1, 5.2 & 5.3 -# Copyright (C) 2011-2018 stdlib authors - -LDOC = ldoc -LUA = lua -MKDIR = mkdir -p -SED = sed -SPECL = specl - -VERSION = git - -luadir = lib/std -SOURCES = \ - $(luadir)/_base.lua \ - $(luadir)/debug.lua \ - $(luadir)/init.lua \ - $(luadir)/io.lua \ - $(luadir)/math.lua \ - $(luadir)/package.lua \ - $(luadir)/string.lua \ - $(luadir)/table.lua \ - $(luadir)/version.lua \ - $(NOTHING_ELSE) - - -all: doc - -$(luadir)/version.lua: .FORCE - @echo 'return "General Lua libraries / $(VERSION)"' > '$@T'; \ - if cmp -s '$@' '$@T'; then \ - rm -f '$@T'; \ - else \ - echo 'echo return "General Lua libraries / $(VERSION)" > $@'; \ - mv '$@T' '$@'; \ - fi - -doc: build-aux/config.ld $(SOURCES) - $(LDOC) -c build-aux/config.ld . - -build-aux/config.ld: build-aux/config.ld.in - $(SED) -e "s,@PACKAGE_VERSION@,$(VERSION)," '$<' > '$@' - - -CHECK_ENV = LUA=$(LUA) - -check: - LUA=$(LUA) $(SPECL) $(SPECL_OPTS) spec/*_spec.yaml - -.FORCE: diff --git a/NEWS.md b/NEWS.md deleted file mode 100644 index fdbf720..0000000 --- a/NEWS.md +++ /dev/null @@ -1,1414 +0,0 @@ -# Stdlib NEWS - User visible changes - -## Noteworthy changes in release ?.? (????-??-??) [?] - -### New features - - - Overhaul of the LDoc documentation, adding more introductory - material, clearer usage examples and better internal consistency. At - this point we're pushing the technical limits of what LDoc can do for - us organization-wise, but improvements and corrections to the content - are always welcome! - - - With this release, stdlib is much more focused, and non-core modules - `optparse`, `std.functional`, 'std.prototype', `std.strict` and - `typecheck` have been moved into their own packages and release - cycle. Also, the shared debug initialization, Lua host normalization - and API deprecation code have been split out into new 'std._debug', - 'std.normalize' and 'apimaturity' respectively, and are pulled in - automatically as dependencies for any of any modules that need them. - You can still install them all separately from their own projects or - by using Luarocks: - - ```bash - luarocks install optparse - luarocks install std.functional - luarocks install std.prototype - luarocks install std.strict - luarocks install typecheck - ``` - - - All support for previously deprecated APIs has been removed, reducing - the install size even further. - - - `std.string.prettytostring` continues to use `normalize.string.render` - for more legible deeply nested table output, identically to previous - releases. - - - `std.npairs` and `std.rnpairs` now respect `__len` metamethod, if any. - - - `std.table.okeys` has been removed for lack of utility. If you - still need it, use this instead: - - ```lua - local okeys = std.functional.compose (std.table.keys, std.table.sort) - ``` - -### Bug fixes - - - `std.string.wrap` doesn't throw a StrBuf deprecation warning any more. - - - `std.getmetamethod` now returns functable valued metamethods - correctly, rather than `nil` as in previous releases. It's also - considerably faster now that it doesn't use `pcall` any more. - - - `table.pack` now sets `n` field to number of arguments packed, even - in Lua 5.1. - -### Incompatible changes - - - `std.container`, `std.functional`, `std.list`, `std.maturity`, - `std.object`, `std.operator`, `std.optparse`, `std.set`, - `std.strbuf`, `std.strict` and `std.tuple` have been moved to their - own packages, and are no longer shipped as part of stdlib. - - - Monkey patching calls `std.barrel`, `std.monkey_patch`, - `std.io.monkey_patch`, `std.math.monkey_patch`, - `std.string.monkey_patch` and `std.table.monkey_patch` have all - been removed. - - - `std.debug.argerror`, `std.debug.argcheck`, `std.debug.argscheck`, - `std.debug.extramsg_mismatch`, `std.debug.extramsg_toomany`, - `std.debug.parsetypes`, `std.debug.resulterror` and `std.debug.typesplit` - have all been moved to their own package, and are no longer shipped - as part of stdlib. - - - `std.debug.DEPRECATED` and `std.debug.DEPRECATIONMSG` have been - removed. At some point these will resurface in a new standalone - package. - - - Deprecated functions `string.assert`, `string.require_version`, - `string.tostring`, `table.clone_rename`, `table.metamethod`, - `table.ripairs` and `table.totable` have been removed. See previous - NEWS entries below for what they were replaced by. - - - Passing a table with a `__len` metamethod, that returns a value other - the index of the largest non-nil valued integer key, to `std.npairs` - now iterates upto whatever `__len` returns rather than `std.table.maxn`. - If `__len` is not present, or gives the same result as `maxn` then - `npairs` continues to behave as in the previous release. - - - `std.tostring` and `std.string.render` have been superceded by their - equivalents from 'std.normalize': `str` and `string.render`. Those - implementations handle skipping initial sequence keys for a more - compact output, escaping of whitespace and other C escape characters - for even more compact output and stringification of nested Objects and - Containers using their `__tostring` metamethods. - - - For consistency with std.normalize and other package symbols, we now - spell `package.path_mark` as `package.pathmark`. - - -## Noteworthy changes in release 41.2.0 (2015-03-08) [stable] - -### New features - - - New iterators, `std.npairs` and `std.rnpairs` behave like - `std.ipairs` and `std.ripairs` resp., except that they will visit - all integer keyed elements, including nil-valued "holes". This is - useful for iterating over argument lists with nils: - - ```lua - function fn(a, b, c) for _, v in npairs {...} do print(v) end - fn(nil, nil, 3) --> nil nil 3 - ``` - - - New `debug.getfenv` and `debug.setfenv` that work with Lua 5.2 and - 5.3. - - - `debug.argscheck` will skip typecheck for `self` parameter if the - function name specification contains a colon. - - - New `debug.resulterror` is much like `debug.argerror`, but uses the - message format "bad result #n from 'fname'". - - - New `debug.extramsg_mismatch` to generate `extramsg` argument for - `debug.argerror` or `debug.resulterror` on encountering a type - mismatch. - - - New `debug.extramsg_toomany` to generate a too many arguments or - similar `extramsg` argument. - -### Deprecations - - - `debug.toomanyargmsg` has been deprecated in favour of the more - orthogal `debug.extramsg_toomany` api. You can rewrite clients of - deprecated api like this: - - ```lua - if maxn(argt) > 7 then - argerror('fname', 8, extramsg_toomany('argument', 7, maxn(argt)), 2) - end - ``` - -### Bug fixes - - - `std.getmetamethod` no longer rejects non-table subjects when - `_DEBUG.argcheck` is set. - - - `functional.bind`, `functional.collect`, `functional.compose`, - `functional.filter` and `functional.map` propagate nil valued - arguments correctly. - - - `functional.callable` no longer raises an argument error when passed - a nil valued argument. - - - `debug.argcheck` and `debug.argscheck` accept "bool" as an alias for - "boolean" consistently. - - - `io.catdir` and `io.dirname` no longer leak extra results from - implementation details. - -### Incompatible changes - - - `functional.collect` uses `std.npairs` as a default iterator rather - than `std.ipairs`. - - -## Noteworthy changes in release 41.1.1 (2015-01-31) [stable] - -### Bug fixes - - - `std.barrel` no longer gets stuck in an infinite loop when called in - Lua 5.3. - - -## Noteworthy changes in release 41.1.0 (2015-01-30) [stable] - -### New features - - - Anything that responds to `tostring` can be appended to a `std.strbuf`: - - ```lua - local a, b = StrBuf {'foo', 'bar'}, StrBuf {'baz', 'quux'} - a = a .. b --> 'foobarbazquux' - ``` - - - `std.strbuf` stringifies lazily, so adding tables to a StrBuf - object, and then changing the content of them before calling - `tostring` also changes the contents of the buffer. See LDocs for - an example. - - - `debug.argscheck` accepts square brackets around final optional - parameters, which is distinct to the old way of appending `?` or - `|nil` in that no spurious "or nil" is reported for type mismatches - against a final bracketed argument. - - - `debug.argscheck` can also check types of function return values, when - specified as: - - ```lua - fn = argscheck('fname(?any...) => int, table or nil, string', fname) - ``` - - Optional results can be marked with brackets, and an ellipsis following - the final type denotes any additional results must match that final - type specification. Alternative result type groups are separated by "or". - - - New `table.unpack(t, [i, [j]])` function that defaults j to - `table.maxn(t)`, even on luajit which stops before the first nil - valued numeric index otherwise. - -### Deprecations - - - `std.strbuf.tostring` has been deprecated in favour of `tostring`. - Why write `std.strbuf.tostring(sb)` or `sb:tostring()` when it is - more idiomatic to write `tostring(sb)`? - -### Bug fixes - - - `std.barrel` and the various `monkey_patch` functions now return - their parent module table as documented. - - - stdlib modules are all `std.strict` compliant; require 'std.strict' - before requiring other modules no longer raises an error. - - - `debug.argscheck` can now diagnose when there are too many arguments, - even in the case where the earlier arguments match parameters by - skipping bracketed optionals, and the total number of arguments is - still less than the absolute maximum allowed if optionals are counted - too. - - - `package.normalize` now leaves valid ./../../ path prefixes unmolested. - -### Incompatible changes - - - `debug.argscheck` requires nil parameter type `?` notation to be - prepended to match Specl and TypedLua syntax. `?` suffixes are a - syntax error. - - - `debug.argscheck` uses `...` instead of `*` appended to the final element - if all unmatched argument types should match. The trailing `*` syntax - was confusing, because it was easy to misread it as "followed by zero-or- - more of this type". - - -## Noteworthy changes in release 41.0.0 (2015-01-03) [beta] - -### New features - - - Preliminary Lua 5.3.0 compatibility. - - - `object.prototype` now reports "file" for open file handles, and - "closed file" for closed file handles. - - - New `debug.argerror` and `debug.argcheck` functions that provide Lua - equivalents of `luaL_argerror` and `luaL_argcheck`. - - - New `debug.argscheck` function for checking all function parameter - types with a single function call in the common case. - - - New `debug.export` function, which returns a wrapper function for - checking all arguments of an inner function against a type list. - - - New `_DEBUG.argcheck` field that disables `debug.argcheck`, and - changes `debug.argscheck` to return its function argument unwrapped, - for production code. Similarly `_DEBUG = false` deactivates these - functions in the same way. - - - New `std.operator` module, with easier to type operator names (`conj`, - `deref`, `diff`, `disj`, `eq`, `neg`, `neq`, `prod`, `quot`, and `sum`), - and a functional operator for concatenation `concat`; plus new mathematical - operators `mod`, and `pow`; and relational operators `lt`, `lte`, `gt` and - `gte`. - - - `functional.case` now accepts non-callable branch values, which are - simply returned as is, and functable values which are called and - their return value propagated back to the case caller. Function - values behave the same as in previous releases. - - - `functional.collect`, `functional.filter`, `functional.map` and - `functional.reduce` now work with standard multi-return iterators, - such as `std.pairs`. - - - `functional.collect` defaults to using `std.ipairs` as an iterator. - - - New `functional.cond`, for evaluating multiple distinct expressions - to determine what following value to be the returned. - - - `functional.filter` and `functional.map` default to using `std.pairs` - as an iterator. - - - The init argument to `functional.foldl` and `functional.foldr` is now - optional; when omitted these functions automatically start with - the left- or right-most element of the table argument resp. - - - New `functional.callable` function for unwrapping objects or - primitives that can be called as if they were a function. - - - New `functional.lambda` function for compiling lambda strings: - - ```lua - table.sort(t, lambda '|a,b| a - explaining why any deprecation should be reinstated or at least kept - around for more than 1 year. - - - By default, deprecated APIs will issue a warning to stderr on every - call. However, in production code, you can turn off these warnings - entirely with any of: - - ```lua - _DEBUG = false - _DEBUG = {deprecate=false} - require 'std.debug_init'.deprecate = false - ``` - - Or, to confirm you're not trying to call a deprecated function at - runtime, you can prevent deprecated functions from being defined at - all with any of: - - ```lua - _DEBUG = true - _DEBUG = {deprecate=true} - require 'std.debug_init'.deprecate = true - ``` - - The `_DEBUG` global must be set before requiring any stdlib modules, - but you can adjust the fields in the `std.debug_init` table at any - time. - - - `functional.eval` has been moved to `std.eval`, the old name now - gives a deprecation warning. - - - `functional.fold` has been renamed to `functional.reduce`, the old - name now gives a deprecation warning. - - - `functional.op` has been moved to a new `std.operator` module, the - old function names now gives deprecation warnings. - - - `list.depair` and `list.enpair` have been moved to `table.depair` and - `table.enpair`, the old names now give deprecation warnings. - - - `list.filter` has been moved to `functional.filter`, the old name now - gives a deprecation warning. - - - `list.flatten` has been moved to `table.flatten`, the old name now - gives a deprecation warning. - - - `list.foldl` and `list.foldr` have been replaced by the richer - `functional.foldl` and `functional.foldr` respectively. The old - names now give a deprecation warning. Note that List object methods - `foldl` and `foldr` are not affected. - - - `list.index_key` and `list.index_value` have been deprecated. These - functions are not general enough to belong in lua-stdlib, because - (among others) they only work correctly with tables that can be - inverted without loss of key values. They currently give deprecation - warnings. - - - `list.map` and `list.map_with` has been deprecated, in favour of the - more powerful new `functional.map` and `functional.map_with` which - handle tables as well as lists. - - - `list.project` has been deprecated in favour of `table.project`, the - old name now gives a deprecation warning. - - - `list.relems` has been deprecated, in favour of the more idiomatic - `functional.compose(std.ireverse, std.ielems)`. - - - `list.reverse` has been deprecated in favour of the more general - and more accurately named `std.ireverse`. - - - `list.shape` has been deprecated in favour of `table.shape`, the old - name now gives a deprecation warning. - - - `list.transpose` has been deprecated in favour of `functional.zip`, - see above for details. - - - `list.zip_with` has been deprecated in favour of `functional.zip_with`, - see above for details. - - - `string.assert` has been moved to `std.assert`, the old name now - gives a deprecation warning. - - - `string.require_version` has been moved to `std.require`, the old - name now gives a deprecation warning. - - - `string.tostring` has been moved to `std.tostring`, the old name now - gives a deprecation warning. - - - `table.metamethod` has been moved to `std.getmetamethod`, the old - name now gives a deprecation warning. - - - `table.ripairs` has been moved to `std.ripairs`, the old name now - gives a deprecation warning. - - - `table.totable` has been deprecated and now gives a warning when used. - -### Incompatible changes - - - `std.monkey_patch` works the same way as the other submodule - monkey_patch functions now, by injecting its methods into the given - (or global) namespace. To get the previous effect of running all the - monkey_patch functions, either run them all manually, or call - `std.barrel()` as before. - - - `functional.bind` sets fixed positional arguments when called as - before, but when the newly bound function is called, those arguments - fill remaining unfixed positions rather than being overwritten by - original fixed arguments. For example, where this would have caused - an error previously, it now prints "100" as expected. - - ```lua - local function add(a, b) return a + b end - local incr = functional.bind(add, {1}) - print(incr(99)) - ``` - - If you have any code that calls functions returned from `bind`, you - need to remove the previously ignored arguments that correspond to - the fixed argument positions in the `bind` invocation. - - - `functional.collect`, `functional.filter` and `functional.map` still - make a list from the results from an iterator that returns single - values, but when an iterator returns multiple values they now make a - table with key:value pairs taken from the first two returned values of - each iteration. - - - The `functional.op` table has been factored out into its own new - module `std.operator`. It will also continue to be available from the - legacy `functional.op` access point for the forseeable future. - - - The `functional.op['..']` operator is no longer a list concatenation - only loaded when `std.list` is required, but a regular string - concatenation just like Lua's `..` operator. - - - `io.catdir` now raises an error when called with no arguments, for - consistency with `io.catfile`. - - - `io.die` no longer calls `io.warn` to write the error message to - stderr, but passes that error message to the core `error` function. - - - `std.set` objects used to be lax about enforcing type correctness in - function arguments, but now that we have strict type-checking on all - apis, table arguments are not coerced to Set objects but raise an - error. Due to an accident of implementation, you can get the old - inconsistent behaviour back for now by turning off type checking - before loading any stdlib modules: - - ```lua - _DEBUG = {argcheck=false} - local set = require 'std.set' - ``` - - - `string.pad` will still (by implementation accident) coerce non- - string initial arguments to a string using `string.tostring` as long - as argument checking is disabled. Under normal circumstances, - passing a non-string will now raise an error as specified in the api - documentation. - - - `table.totable` is deprecated, and thus objects no longer provide or - use a `__totable` metamethod. Instead, using a `__pairs` metamethod - to return key/value pairs, and that will automatically be used by - `__tostring`, `object.mapfields` etc. The base object now provides a - `__pairs` metamethod that returns key/value pairs in order, and - ignores private fields. If you have objects that relied on the - previous treatment of `__totable`, please convert them to set a - custom `__pairs` instead. - - -### Bug fixes - - - Removed LDocs for unused `_DEBUG.std` field. - - - `debug.trace` works with Lua 5.2.x again. - - - `list:foldr` works again instead of raising a "bad argument #1 to - 'List'" error. - - - `list.transpose` works again, and handles empty lists without - raising an error; but is deprecated and will be removed in a future - release (see above). - - - `list.zip_with` no longer raises an argument error on every call; but, - like `list.transpose`, is also deprecated (see above). - - - `optparse.on` now works with `std.strict` enabled. - - - `std.require` (nee `string.require_version`) now extracts the last - substring made entirely of digits and periods from the required - module's version string before splitting on period. That means, for - version strings like luaposix's "posix library for Lua 5.2 / 32" we - now correctly compare just the numeric part against specified version - range rather than an ASCII comparison of the whole thing as before! - - - The documentation now correcly notes that `std.require` looks - first in `module.version` and then `module._VERSION` to match the - long-standing implementation. - - - `string.split` now really does split on whitespace when no split - pattern argument is provided. Also, the documentation now - correctly cites `%s+` as the default whitespace splitting pattern - (not `%s*` which splits between every non-whitespace character). - - -## Noteworthy changes in release 40 (2014-05-01) [stable] - -### New features - - - `functional.memoize` now accepts a user normalization function, - falling back on `string.tostring` otherwise. - - - `table.merge` now supports `map` and `nometa` arguments orthogonally - to `table.clone`. - - - New `table.merge_select` function, orthogonal to - `table.clone_select`. See LDocs for details. - -### Incompatible changes - - - Core methods and metamethods are no longer monkey patched by default - when you `require 'std'` (or `std.io`, `std.math`, `std.string` or - `std.table`). Instead they provide a new `monkey_patch` method you - should use when you don't care about interactions with other - modules: - - ```lua - local io = require 'std.io'.monkey_patch() - ``` - - To install all of stdlib's monkey patches, the `std` module itself - has a `monkey_patch` method that loads all submodules with their own - `monkey_patch` method and runs them all. - - If you want full compatibility with the previous release, in addition - to the global namespace scribbling snippet above, then you need to - adjust the first line to: - - ```lua - local std = require 'std'.monkey_patch() - ``` - - - The global namespace is no longer clobbered by `require 'std'`. To - get the old behaviour back: - - ```lua - local std = require 'std'.barrel(_G) - ``` - - This will execute all available monkey_patch functions, and then - scribble all over the `_G` namespace, just like the old days. - - - The `metamethod` call is no longer in `std.functional`, but has moved - to `std.table` where it properly belongs. It is a utility method for - tables and has nothing to do with functional programming. - - - The following deprecated camelCase names have been removed, you - should update your code to use the snake_case equivalents: - `std.io.processFiles`, `std.list.indexKey`, `std.list.indexValue`, - `std.list.mapWith`, `std.list.zipWith`, `std.string.escapePattern`, - `std.string. escapeShell`, `std.string.ordinalSuffix`. - - - The following deprecated function names have been removed: - `std.list.new` (call `std.list` directly instead), - `std.list.slice` (use `std.list.sub` instead), - `std.set.new` (call `std.set` directly instead), - `std.strbuf.new` (call `std.strbuf` directly instead), and - `std.tree.new` (call `std.tree` directly instead). - -### Bug fixes - - - Allow `std.object` derived tables as `std.tree` keys again. - - -## Noteworthy changes in release 39 (2014-04-23) [stable] - -### New features - - - New `std.functional.case` function for rudimentary case statements. - The main difference from serial if/elseif/end comparisons is that - `with` is evaluated only once, and then the match function is looked - up with an O(1) table reference and function call, as opposed to - hoisting an expression result into a temporary variable, and O(n) - comparisons. - - The function call overhead is much more significant than several - comparisons, and so `case` is slower for all but the largest series - of if/elseif/end comparisons. It can make your code more readable, - however. - - See LDocs for usage. - - - New pathstring management functions in `std.package`. - - Manage `package.path` with normalization, duplicate removal, - insertion & removal of elements and automatic folding of '/' and '?' - onto `package.dirsep` and `package.path_mark`, for easy addition of - new paths. For example, instead of all this: - - ```lua - lib = std.io.catfile('.', 'lib', package.path_mark .. '.lua') - paths = std.string.split(package.path, package.pathsep) - for i, path in ipairs(paths) do - -- ... lots of normalization code... - end - i = 1 - while i <= #paths do - if paths[i] == lib then - table.remove(paths, i) - else - i = i + 1 - end - end - table.insert(paths, 1, lib) - package.path = table.concat(paths, package.pathsep) - ``` - - You can now write just: - - ```lua - package.path = package.normalize('./lib/?.lua', package.path) - ``` - - - `std.optparse:parse` accepts a second optional parameter, a table of - default option values. - - - `table.clone` accepts an optional table of key field renames in the - form of `{oldkey=newkey, ...}` subsuming the functionality of - `table.clone_rename`. The final `nometa` parameter is supported - whether or not a rename map is given: - - ```lua - r = table.clone(t, 'nometa') - r = table.clone(t, {oldkey=newkey}, 'nometa') - ``` - -### Deprecations - - - `table.clone_rename` now gives a warning on first call, and will be - removed entirely in a few releases. The functionality has been - subsumed by the improvements to `table.clone` described above. - -### Bug fixes - - - `std.optparse` no longer throws an error when it encounters an - unhandled option in a combined (i.e. `-xyz`) short option string. - - - Surplus unmapped fields are now discarded during object cloning, for - example when a prototype has `_init` set to `{'first', 'second'}`, - and is cloned using `Proto {'one', 'two', 'three'}`, then the - unmapped `three` argument is now discarded. - - - The path element returned by `std.tree.nodes` can now always be - used as a key list to dereference the root of the tree, particularly - `tree[{}]` now returns the root node of `tree`, to match the initial - `branch` and final `join` results from a full traversal by - `std.tree.nodes(tree)`. - -### Incompatible changes - - - `std.string` no longer sets `__append`, `__concat` and `__index` in - the core strings metatable by default, though `require 'std'` does - continue to do so. See LDocs for `std.string` for details. - - - `std.optparse` no longer normalizes unhandled options. For example, - `--unhandled-option=argument` is returned unmolested from `parse`, - rather than as two elements split on the `=`; and if a combined - short option string contains an unhandled option, then whatever was - typed at the command line is returned unmolested, rather than first - stripping off and processing handled options, and returning only the - unhandled substring. - - - Setting `_init` to `{}` in a prototype object will now discard all - positional parameters passed during cloning, because a table valued - `_init` is a list of field names, beyond which surplus arguments (in - this case, all arguments!) are discarded. - - -## Noteworthy changes in release 38 (2014-01-30) [stable] - -### New features - - - The separator parameter to `std.string.split` is now optional. It - now splits strings with `%s+` when no separator is specified. The - new implementation is faster too. - - - New `std.object.mapfields` method factors out the table field copying - and mapping performed when cloning a table `_init` style object. This - means you can call it from a function `_init` style object after - collecting a table to serve as `src` to support derived objects with - normal std.object syntax: - - ```lua - Proto = Object { - _type = 'proto' - _init = function(self, arg, ...) - if type(arg) == 'table' then - mapfields(self, arg) - else - -- non-table instantiation code - end - end, - } - new = Proto(str, #str) - Derived = proto {_type='Derived', ...} - ``` - - - Much faster object cloning; `mapfields` is in imperative style and - makes one pass over each table it looks at, where previous releases - used functional style (stack frame overhead) and multiple passes over - input tables. - - On my 2013 Macbook Air with 1.3GHz Core i5 CPU, I can now create a - million std.objects with several assorted fields in 3.2s. Prior to - this release, the same process took 8.15s... and even release 34.1, - with drastically simpler Objects (19SLOC vs over 120) took 5.45s. - - - `std.object.prototype` is now almost an order of magnitude faster - than previous releases, taking about 20% of the time it previously - used to return its results. - - - `io.warn` and `io.die` now integrate properly with `std.optparse`, - provided you save the `opts` return from `parser:parse` back to the - global namespace where they can access it: - - ```lua - local OptionParser = require 'std.optparse' - local parser = OptionParser 'eg 0\nUsage: eg\n' - _G.arg, _G.opts = parser:parse(_G.arg) - if not _G.opts.keep_going then - require 'std.io'.warn 'oh noes!' - end - ``` - - will, when run, output to stderr: "eg: oh noes!" - -### Bug fixes - - - Much improved documentation for `optparse`, so you should be able - to use it without reading the source code now! - - - `io.warn` and `io.die` no longer output a line-number when there is - no file name to append it to. - - - `io.warn` and `io.die` no longer crash in the absence of a global - `prog` table. - - - `string.split` no longer goes into an infinite loop when given an - empty separator string. - - - Fix `getmetatable(container._functions) == getmetatable(container)`, - which made tostring on containers misbehave, among other latent bugs. - - - `_functions` is never copied into a metatable now, finally solving - the conflicted concerns of needing metatables to be shared between - all objects of the same `_type` (for `__lt` to work correctly for one - thing) and not leaving a dangling `_functions` list in the metatable - of cloned objects, which could delete functions with matching names - from subsequent clones. - - -## Noteworthy changes in release 37 (2014-01-19) [stable] - -### New features - - - Lazy loading of submodules into `std` on first reference. On initial - load, `std` has the usual single `version` entry, but the `__index` - metatable will automatically require submodules on first reference: - - ```lua - local std = require 'std' - local prototype = std.container.prototype - ``` - - - New `std.optparse` module: A civilised option parser. - (L)Documentation distributed in doc/classes/std.optparse.html. - -### Bug fixes - - - Modules no longer leak `new' and `proper_subset' into the global - table. - - - Cloned `Object` and `Container` derived types are more aggressive - about sharing metatables, where previously the metatable was copied - unnecessarily the base object used `_functions` for module functions - - - The retracted release 36 changed the operand order of many `std.list` - module functions unnecessarily. Now that `_function` support is - available, there's no need to be so draconian, so the original v35 - and earlier operand order works as before again. - - - `std.list.new`, `std.set.new`, `set.strbuf.new` and `std.tree.new` - are available again for backwards compatibility. - - - LuaRocks install doesn't copy config.ld and config.ld to $docdir. - -### Incompatible changes - - - `std.getopt` is no more. It appears to have no users, though if there - is a great outcry, it should be easy to make a compatibility api over - `std.optparse` in the next release. - - -## Noteworthy changes in release 36 (2014-01-16) [stable] - -### New features - - - Modules have been refactored so that they can be safely - required individually, and without loading themselves or any - dependencies on other std modules into the global namespace. - - - Objects derived from the `std.object` prototype have a new - :prototype() method that returns the contents of the - new internal `_type` field. This can be overridden during cloning - with, e.g.: - - ```lua - local Object = require 'std.object' - Prototype = Object {_type='Prototype', } - ``` - - - Objects derived from the `std.object` prototype return a new table - with a shallow copy of all non-private fields (keys that do not - begin with '_') when passed to `table.totable` - unless overridden - in the derived object's __totable field. - - - list and strbuf are now derived from `std.object`, which means that - they respond to `object.prototype` with appropriate type names ('List', - 'StrBuf', etc.) and can be used as prototypes for further derived - objects or clones; support object:prototype(); respond to totable etc. - - - A new Container module at `std.container` makes separation between - container objects (which are free to use __index as a '[]' access - metamethod, but) which have no object methods, and regular objects - (which do have object methods, but) which cannot use the __index - metamethod for '[]' access to object contents. - - - set and tree are now derived from `std.container`, so there are no - object methods. Instead there are a full complement of equivalent - module functions. Metamethods continue to work as before. - - - `string.prettytostring` always displays table elements in the same - order, as provided by `table.sort`. - - - `table.totable` now accepts a string, and returns a list of the - characters that comprise the string. - - - Can now be installed directly from a release tarball by `luarocks`. - No need to run `./configure` or `make`, unless you want to install to - a custom location, or do not use LuaRocks. - -### Bug fixes - - - string.escape_pattern is now Lua 5.2 compatible. - - - all objects now reuse prototype metatables, as required for __le and - __lt metamethods to work as documented. - -### Deprecations - - - To avoid confusion between the builtin Lua `type` function and the - method for finding the object prototype names, `std.object.type` is - deprecated in favour of `std.object.prototype`. `std.object.type` - continues to work for now, but might be removed from a future - release. - - ```lua - local prototype = require 'std.object'.prototype - ``` - - ...makes for more readable code, rather than confusion between the - different flavours of `type`. - -### Incompatible changes - - - Following on from the Grand Renaming™ change in the last release, - `std.debug_ext`, `std.io_ext`, `std.math_ext`, `std.package_ext`, - `std.string_ext` and `std.table_ext` no longer have the spurious - `_ext` suffix. Instead, you must now use, e.g.: - - ```lua - local string = require 'std.string' - ``` - - These names are now stable, and will be available from here for - future releases. - - - The `std.list` module, as a consequence of returning a List object - prototype rather than a table of functions including a constructor, - now always has the list operand as the first argument, whether that - function is called with `.` syntax or `:` syntax. Functions which - previously had the list operand in a different position when called - with `.` syntax were: list.filter, list.foldl, list.foldr, - list.index_key, list.index_value, list.map, list.map_with, - list.project, list.shape and list.zip_with. Calls made as object - methods using `:` calling syntax are unchanged. - - - The `std.set` module is a `std.container` with no object methods, - and now uses prototype functions instead: - - ```lua - local union = Set.union(set1, set2) - ``` - - -## Noteworthy changes in release 35 (2013-05-06) [stable] - -### New features - - - Move to the Slingshot release system. - - Continuous integration from Travis automatically builds stdilb - with Lua 5.1, Lua 5.2 and luajit-2.0 with every commit, which - should help prevent future release breaking compatibility with - one or another of those interpreters. - -### Bug fixes - - - `std.package_ext` no longer overwrites the core `package` table, - leaving the core holding on to memory that Lua code could no - longer access. - -### Incompatible changes - - - The Grand Renaming™ - everything now installs to $luaprefix/std/, - except `std.lua` itself. Importing individual modules now involves: - - ```lua - local list = require 'std.list' - ``` - - If you want to have all the symbols previously available from the - global and core module namespaces, you will need to put them there - yourself, or import everything with: - - ```lua - require 'std' - ``` - - which still behaves per previous releases. - - Not all of the modules work correctly when imported individually - right now, until we figure out how to break some circular dependencies. - - -## Noteworthy changes in release 34.1 (2013-04-01) [stable] - - - This is a maintenance release to quickly fix a breakage in getopt - from release v34. Getopt no longer parses non-options, but stops - on the first non-option... if a use case for the other method - comes up, we can always add it back in. - - -## Noteworthy changes in release 34 (2013-03-25) [stable] - - - stdlib is moving towards supporting separate requirement of individual - modules, without scribbling on the global environment; the work is not - yet complete, but we're collecting tests along the way to ensure that - once it is all working, it will carry on working; - - - there are some requirement loops between modules, so not everything can - be required independently just now; - - - `require 'std'` will continue to inject std symbols into the system - tables for backwards compatibility; - - - stdlib no longer ships a copy of Specl, which you will need to install - separately if you want to run the bundled tests; - - - getopt supports parsing of undefined options; useful for programs that - wrap other programs; - - - getopt.Option constructor is no longer used, pass a plain Lua table of - options, and getopt will do the rest; - - -## Noteworthy changes in release 33 (2013-07-27) [stable] - - - This release improves stability where Specl has helped locate some - corner cases that are now fixed. - - - `string_ext.wrap` and `string_ext.tfind` now diagnose invalid arguments. - - - Specl code coverage is improving. - - - OrdinalSuffix improvements. - - - Use '%' instead of math.mod, as the latter does not exist in Lua 5.2. - - - Accept negative arguments. - - -## Noteworthy changes in release 32 (2013-02-22) [stable] - - - This release fixes a critical bug preventing getopt from returning - anything in getopt.opt. Gary V. Vaughan is now a co-maintainer, currently - reworking the sources to use (Lua 5.1 compatible) Lua 5.2 style module - packaging, which requires you to assign the return values from your imports: - - ```lua - getopt = require 'getopt' - ``` - - - Extension modules, table_ext, package_ext etc. return the unextended module - table before injecting additional package methods, so you can ignore those - return values or save them for programatically backing out the changes: - - ```lua - table_unextended = require 'table_ext' - ``` - - - Additionally, Specl (see http://github.com/gvvaughan/specl/) specifications - are being written for stdlib modules to help us stop accidentally breaking - things between releases. - - -## Noteworthy changes in release 31 (2013-02-20) [stable] - - - This release improves the list module: lists now have methods, list.slice - is renamed to list.sub (the old name is provided as an alias for backwards - compatibility), and all functions that construct a new list return a proper - list, not a table. As a result, it is now often possible to write code that - works on both lists and strings. - - -## Noteworthy changes in release 30 (2013-02-17) [stable] - - - This release changes some modules to be written in a Lua 5.2 style (but - not the way they work with 5.1). Some fixes and improvements were made to - the build system. Bugs in the die function, the parser module, and a nasty - bug in the set module introduced in the last release (29) were fixed. - - -## Noteworthy changes in release 29 (2013-02-06) [stable] - - - This release overhauls the build system to have LuaRocks install releases - directly from git rather than from tarballs, and fixes a bug in set (issue - #8). - - -## Noteworthy changes in release 28 (2012-10-28) [stable] - - - This release improves the documentation and build system, and improves - require_version to work by default with more libraries. - - -## Noteworthy changes in release 27 (2012-10-03) [stable] - - - This release changes getopt to return all arguments in a list, rather than - optionally processing them with a function, fixes an incorrect definition - of set.elems introduced in release 26, turns on debugging by default, - removes the not-very-useful string.gsubs, adds constructor functions for - objects, renames table.rearrange to the more descriptive table.clone_rename - and table.indices to table.keys, and makes table.merge not clone but modify - its left-hand argument. A function require_version has been added to allow - version constraints on a module being required. Gary Vaughan has - contributed a memoize function, and minor documentation and build system - improvements have been made. Usage information is now output to stdout, not - stderr. The build system has been fixed to accept Lua 5.2. The luarock now - installs documentation, and the build command used is now more robust - against previous builds in the same tree. - - -## Noteworthy changes in release 26 (2012-02-18) [stable] - - - This release improves getopt's output messages and conformance to - standard practice for default options. io.processFiles now unsets prog.file - when it finishes, so that a program can tell when itâs no longer - processing a file. Three new tree iterators, inodes, leaves and ileaves, - have been added; the set iterator set.elements (renamed to set.elems for - consistency with list.elems) is now leaves rather than pairs. tree indexing - has been made to work in more circumstances (thanks, Gary Vaughan). - io.writeline is renamed io.writelines for consistency with io.readlines and - its function. A slurping function, io.slurp, has been added. Strings now - have a __concat metamethod. - - -## Noteworthy changes in release 25 (2011-09-19) [stable] - - - This release adds a version string to the std module and fixes a buglet in - the build system. - - -## Noteworthy changes in release 24 (2011-09-19) [stable] - - - This release fixes a rename missing from release 23, and makes a couple of - fixes to the new build system, also from release 23. - - -## Noteworthy changes in release 23 (2011-09-17) [stable] - - - This release removes the posix_ext module, which is now part of luaposix, - renames string.findl to string.tfind to be the same as lrexlib, and - autotoolizes the build system, as well as providing a rockspec file. - - -## Noteworthy changes in release 22 (2011-09-02) [stable] - - - This release adds two new modules: strbuf, a trivial string buffers - implementation, which is used to speed up the stdlib tostring method for - tables, and bin, which contains a couple of routines for converting binary - data into numbers and strings. Some small documentation and build system - fixes have been made. - - -## Noteworthy changes in release 21 (2011-06-06) [stable] - - - This release converts the documentation of stdlib to LuaDoc, adds an - experimental Lua 5.2 module "fstable", for storing tables directly on - disk as files and directories, and fixes a few minor bugs (with help from - David Favro). - - - This release has been tested lightly on Lua 5.2 alpha, but is not - guaranteed to work fully. - - -## Noteworthy changes in release 20 (2011-04-14) [stable] - - - This release fixes a conflict between the global _DEBUG setting and the use - of strict.lua, changes the argument order of some list functions to favour - OO-style use, adds posix.euidaccess, and adds OO-style use to set. mk1file - can now produce a single-file version of a user-supplied list of modules, - not just the standard set. - - -## Noteworthy changes in release 19 (2011-02-26) [stable] - - - This release puts the package.config reflection in a new package_ext - module, where it belongs. Thanks to David Manura for this point, and for a - small improvement to the code. - - -## Noteworthy changes in release 18 (2011-02-26) [stable] - - - This release provides named access to the contents of package.config, which - is undocumented in Lua 5.1. See luaconf.h and the Lua 5.2 manual for more - details. - - -## Noteworthy changes in release 17 (2011-02-07) [stable] - - - This release fixes two bugs in string.pad (thanks to Bob Chapman for the - fixes). - - -## Noteworthy changes in release 16 (2010-12-09) [stable] - - - Adds posix module, using luaposix, and makes various other small fixes and - improvements. - - -## Noteworthy changes in release 15 (2010-06-14) [stable] - - - This release fixes list.foldl, list.foldr, the fold iterator combinator and - io.writeLine. It also simplifies the op table, which now merely sugars the - built-in operators rather than extending them. It adds a new tree module, - which subsumes the old table.deepclone and table.lookup functions. - table.subscript has become op['[]'], and table.subscripts has been removed; - the old treeIter iterator has been simplified and generalised, and renamed - to nodes. The mk1file script and std.lua library loader have had the module - list factored out into modules.lua. strict.lua from the Lua distribution is - now included in stdlib, which has been fixed to work with it. Some minor - documentation and other code improvements and fixes have been made. - - -## Noteworthy changes in release 14 (2010-06-07) [stable] - - - This release makes stdlib compatible with strict.lua, which required a - small change to the debug_ext module. Some other minor changes have also - been made to that module. The table.subscripts function has been removed - from the table_ext.lua. - - -## Noteworthy changes in release 13 (2010-06-02) [stable] - - - This release removes the lcs module from the standard set loaded by - 'std', removes an unnecessary definition of print, and tidies up the - implementation of the "op" table of functional versions of the infix - operators and logical operators. - - -## Noteworthy changes in release 12 (2009-09-07) [stable] - - - This release removes io.basename and io.dirname, which are now available in - lposix, and the little-used functions addSuffix and changeSuffix which - dependend on them. io.pathConcat is renamed to io.catdir and io.pathSplit - to io.splitdir, making them behave the same as the corresponding Perl - functions. The dependency on lrexlib has been removed along with the rex - wrapper module. Some of the more esoteric and special-purpose modules - (mbox, xml, parser) are no longer loaded by 'require 'std''. - - This leaves stdlib with no external dependencies, and a rather more - coherent set of basic modules. - - -## Noteworthy changes in release 11 (2009-03-15) [stable] - - - This release fixes a bug in string.format, removes the redundant - string.join (it's the same as table.concat), and adds to table.clone and - table.deepclone the ability to copy without metatables. Thanks to David - Kantowitz for pointing out the various deficiencies. - - -## Noteworthy changes in release 10 (2009-03-13) [stable] - - - This release fixes table.deepclone to copy metatables, as it should. - Thanks to David Kantowitz for the fix. - - -## Noteworthy changes in release 9 (2009-02-19) [stable] - - - This release updates the object module to be the same as that published - in "Lua Gems", and fixes a bug in the utility mk1file which makes a - one-file version of the library, to stop it permanently redefining require. - - -## Noteworthy changes in release 8 (2008-09-04) [stable] - - - This release features fixes and improvements to the set module; thanks to - Jiutian Yanling for a bug report and suggestion which led to this work. - - -## Noteworthy changes in release 7 (2008-09-04) [stable] - - - just a bug fix - - -## Noteworthy changes in release 6 (2008-07-28) [stable] - - - This release rewrites the iterators in a more Lua-ish 5.1 style. - - -## Noteworthy changes in release 5 (2008-03-04) [stable] - - - I'm happy to announce a new release of my standard Lua libraries. It's been - nearly a year since the last release, and I'm happy to say that since then - only one bug has been found (thanks Roberto!). Two functions have been - added in this release, to deal with file paths, and one removed (io.length, - which is handled by lfs.attributes) along with one constant (INTEGER_BITS, - handled by bitlib's bit.bits). - - - For those not familiar with stdlib, it's a pure-Lua library of mostly - fundamental data structures and algorithms, in particular support for - functional and object-oriented programming, string and regex operations and - extensible pretty printing of data structures. More specific modules - include a getopt implementation, a generalised least common subsequences - (i.e. diff algorithm) implementation, a recursive-descent parser generator, - and an mbox parser. - - - It's quite a mixed bag, but almost all written for real projects. It's - written in a doc-string-ish style with the supplied very simple ldoc tool. - - - I am happy with this code base, but there are various things it could use: - - 0. Tests. Tests. Tests. The code has no unit tests. It so needs them. - - 1. More code. Nothing too specialised (unless it's too small to be released - on its own, although very little seems "too small" in the Lua - community). Anything that either has widespread applicability (like - getopt) or is very general (data structures, algorithms, design - patterns) is good. - - 2. Refactoring. The code is not ideally factored. At the moment it is - divided into modules that extend existing libraries, and new modules - constructed along similar lines, but I think that some of the divisions - are confusing. For example, the functional programming support is spread - between the list and base modules, and would probably be better in its - own module, as those who aren't interested in the functional style won't - want the functional list support or the higher-order functions support, - and those who want one will probably want the other. - - 3. Documentation work. There's not a long wrong with the existing - documentation, but it would be nice, now that there is a stable LuaDoc, - to use that instead of the built-in ldoc, which I'm happy to discard now - that LuaDoc is stable. ldoc was always designed as a minimal LuaDoc - substitute in any case. - - 4. Maintenance and advocacy. For a while I have been reducing my work on - Lua, and am also now reducing my work in Lua. If anyone would like to - take on stdlib, please talk to me. It fills a much-needed function: I - suspect a lot of Lua programmers have invented the wheels with which it - is filled over and over again. In particular, many programmers could - benefit from the simplicity of its simple and well-designed functional, - string and regex capabilities, and others will love its comprehensive - getopt. - - -## Noteworthy changes in release 4 (2007-04-26) [beta] - - - This release removes the dependency on the currently unmaintained lposix - library, includes pre-built HTML documentation, and fixes some 5.0-style - uses of variadic arguments. - - Thanks to Matt for pointing out all these problems. stdlib is very much - user-driven at the moment, since it already does everything I need, and I - don't have much time to work on it, so do please contact me if you find - bugs or problems or simply don't understand it, as the one thing I *do* - want to do is make it useful and accessible! - - -## Noteworthy changes in release 3 (2007-02-25) [beta] - - - This release fixes the "set" and "lcs" (longest common subsequence, or - "grep") libraries, which were broken, and adds one or two other bug and - design fixes. Thanks are due to Enrico Tassi for pointing out some of the - problems. - - -## Noteworthy changes in release 2 (2007-01-05) [beta] - - - This release includes some bug fixes, and compatibility with lrexlib 2.0. - - -## Noteworthy changes in release 1 (2011-09-02) [beta] - - - It's just a snapshot of CVS, but it's pretty stable at the moment; stdlib, - until such time as greater interest or participation enables (or forces!) - formal releases will be in permanent beta, and tracking CVS is recommended. - - -[optparse]: https://github.com/gvvaughan/optparse -[strict]: https://github.com/lua-stdlib/strict diff --git a/README.md b/README.md deleted file mode 100644 index 49b0328..0000000 --- a/README.md +++ /dev/null @@ -1,92 +0,0 @@ -Standard Lua libraries -====================== - -Copyright (C) 2000-2018 [stdlib authors][github] - -[![License](http://img.shields.io/:license-mit-blue.svg)](http://mit-license.org) -[![travis-ci status](https://secure.travis-ci.org/lua-stdlib/lua-stdlib.png?branch=master)](http://travis-ci.org/lua-stdlib/lua-stdlib/builds) -[![codecov.io](https://codecov.io/gh/lua-stdlib/lua-stdlib/branch/master/graph/badge.svg)](https://codecov.io/gh/lua-stdlib/lua-stdlib) -[![Stories in Ready](https://badge.waffle.io/lua-stdlib/lua-stdlib.png?label=ready&title=Ready)](https://waffle.io/lua-stdlib/lua-stdlib) - - -This is a collection of Lua libraries for Lua 5.1 (including LuaJIT), 5.2 -and 5.3. The libraries are copyright by their authors (see the [AUTHORS][] -file for details), and released under the [MIT license][mit] (the same -license as Lua itself). There is no warranty. - -_stdlib_ has no run-time prerequisites beyond a standard Lua system, -though it will take advantage of [strict][] and [typecheck][] if they -are installed. - -[authors]: http://github.com/lua-stdlib/lua-stdlib/blob/master/AUTHORS.md -[github]: http://github.com/lua-stdlib/lua-stdlib/ "Github repository" -[lua]: http://www.lua.org "The Lua Project" -[mit]: http://mit-license.org "MIT License" -[strict]: https://github.com/lua-stdlib/strict "strict variables" -[typecheck]: https://github.com/gvvaughan/typecheck "function type checks" - - -Installation ------------- - -The simplest and best way to install stdlib is with [LuaRocks][]. To -install the latest release (recommended): - -```bash - luarocks install stdlib -``` - -To install current git master (for testing, before submitting a bug -report for example): - -```bash - luarocks install http://raw.githubusercontent.com/lua-stdlib/lua-stdlib/master/stdlib-git-1.rockspec -``` - -The best way to install without [LuaRocks][] is to copy the `std` -folder and its contents into a directory on your package search path. - -[luarocks]: http://www.luarocks.org "Lua package manager" - - -Documentation -------------- - -The latest release of these libraries is [documented in LDoc][github.io]. -Pre-built HTML files are included in the release. - -[github.io]: http://lua-stdlib.github.io/lua-stdlib - - -Bug reports and code contributions ----------------------------------- - -These libraries are written and maintained by their users. - -Please make bug reports and suggestions as [GitHub Issues][issues]. -Pull requests are especially appreciated. - -But first, please check that your issue has not already been reported by -someone else, and that it is not already fixed by [master][github] in -preparation for the next release (see Installation section above for how -to temporarily install master with [LuaRocks][]). - -There is no strict coding style, but please bear in mind the following -points when proposing changes: - -0. Follow existing code. There are a lot of useful patterns and avoided - traps there. - -1. 3-character indentation using SPACES in Lua sources: It makes rogue - TABS easier to see, and lines up nicely with 'if' and 'end' keywords. - -2. Simple strings are easiest to type using single-quote delimiters, - saving double-quotes for where a string contains apostrophes. - -3. Save horizontal space by only using SPACES where the parser requires - them. - -4. Use vertical space to separate out compound statements to help the - coverage reports discover untested lines. - -[issues]: http://github.com/lua-stdlib/lua-stdlib/issues diff --git a/STYLE.md b/STYLE.md deleted file mode 100644 index f01f630..0000000 --- a/STYLE.md +++ /dev/null @@ -1,97 +0,0 @@ -## Lua - - - Requiring any stdlib module must not leak any symbols into the global - namespace. - - - Any stdlib module may `require "std.base"`, and use any functions from - there, as well as functions from `std.debug` (and `debug_init`); but, - all other modules export argument checked functions that should not be - called from anywhere in stdlib -- this is the client API. If a - function is needed by more than one module, move it to `std.base` - without argument checking, and re-export with `argscheck` if necess- - ary. - - Obviously, for objects it's perfectly fine to require the file that - defines the object being derived from. But to prevent accidentally - calling argchecked methods, we always immediately create a prototype - object with, e.g: - - local Container = require "std.container" {} - - (`std.object` is an exception to this rule because of how tightly - bound to `std.container` it is, and does directly call some of - containers methods by design). - - - Minimise forward declarations of functions, because having some - declared as `local` in line, and others not is ugly and can easily - cause rogue `local` keywords to be introduced that end up shadowing - the intended declaration. Mutually recursive functions, and - alternate definitions are acceptable, in which case keep the forward - declarations and definitions as close together as possible to - minimise any possible misunderstandings later. - - - Try to maintain asciibetical ordering of function definitions in each - source file, except where doing so would require forward declar- - ations. In that case use topological ordering to avoid the forward - declarations. - - - Unless a table cannot possibly have a __len metamethod (i.e. it was - constructed without one in the current scope), always use - `base.insert` and `base.len` rather than core `table.insert` and the - `#` operator, which do not honor __len in all implementations. - - - Unless a table cannot possibly have __pairs or __len metamethods - (i.e. it was constructed without them in the current scope), always - use `base.pairs` or `base.ipairs` rather than core `pairs` and - `ipairs`, which do not honor __pairs or __len in all implementations. - - - Use consistent short names for common parameters: - - fh a file handle, usually from io.open or similar - fmt a format string - fn a function - i an index - k a value, usually from pairs or similar - l a list-like table - n a number - s a string - t a table - - - Do argument check all object methods (functions available from an - object created by a module function -- usually listed in the - `__index` subtable of the object metatable), to catch pathological - calls early, preferably using a `typecheck.argscheck` wrapper around - the internal implementation: this way, implementation functions can - call each other without excessive rechecking of argument types. - - - Do argument check all module functions (functions available in the - table returned from requiring that module). - - - Do argument check metamethods, to catch pathological calls early. - - -## LDocs - - - LDocs should be next to each function's argcheck wrapper (if it has - one) in the export table, so that it's easy to check the consistency - between the types declared in the LDocs and the argument types - enforced by `typecheck.argscheck` or equivalent. - - - `backtick_references` is disabled for stdlib, if you want an inline - cross-reference, use `@{reference}`. - - - Be liberal with `@see` references to similar apis. - - - Refer to other argument names with italics (`*italic*` in markdown). - - - Try to add entries for callback function signatures, and name them - with the suffix `cb`. - - - Rely on the reader to understand how `:` call syntax works in Lua, and - don't waste effort documenting methods that are already documented as - functions. - - - Do document the prototype chain. Don't document methods inherited - from the prototype, even they have been overridden to behave consist- - ently from a UI perspective even though the implementation needs to be - different to provide that same UI. diff --git a/build-aux/config.ld.in b/build-aux/config.ld.in deleted file mode 100644 index 20ee48b..0000000 --- a/build-aux/config.ld.in +++ /dev/null @@ -1,53 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] - -title = 'stdlib @PACKAGE_VERSION@ Reference' -project = 'stdlib @PACKAGE_VERSION@' -description = [[ -# Standard Lua Libraries - -This is a collection of light-weight libraries for Lua 5.1 (including -LuaJIT), 5.2 and 5.3 written in pure Lua, comprising: - -1. Enhanced and expanded versions of some core Lua functions in the - @{std} module itself; - -2. Enhanced versions of some core Lua libraries: @{std.debug}, @{std.io}, - @{std.math}, @{std.package}, @{std.string} and @{std.table}; - -## LICENSE - -The code is copyright by its respective authors, and released under the -MIT license (the same license as Lua itself). There is no warranty. -]] - -dir = '../doc' - -file = { - '../lib/std/init.lua', - '../lib/std/debug.lua', - '../lib/std/io.lua', - '../lib/std/math.lua', - '../lib/std/package.lua', - '../lib/std/string.lua', - '../lib/std/table.lua', -} - -new_type ('corefunction', 'Core_Functions', true) -new_type ('corelibrary', 'Core_Libraries', true) - -function postprocess_html(s) - s = s:gsub('

%s*Corefunction (.-)

', '

Module %1

') - s = s:gsub('

%s*Corelibrary (.-)

', '

Module %1

') - s = s:gsub('

Core_Functions

', '

Core Functions

') - s = s:gsub('

Core_Libraries

', '

Core Libraries

') - return s -end - -new_type ('init', 'Initialisation', false, 'Parameters') - -format = 'markdown' -backtick_references = false -sort = false diff --git a/classes/std.container.html b/classes/std.container.html new file mode 100644 index 0000000..acdfc83 --- /dev/null +++ b/classes/std.container.html @@ -0,0 +1,179 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Class std.container

+

Container prototype.

+

+ + +

A container is a std.object with no methods. It's functionality is + instead defined by its metamethods.

+ +

Where an Object uses the __index metatable entry to hold object + methods, a Container stores its contents using __index, preventing + it from having methods in there too.

+ +

Although there are no actual methods, Containers are free to use + metamethods (__index, __sub, etc) and, like Objects, can supply + module functions by listing them in _functions. Also, since a + std.container is a std.object, it can be passed to the + std.object module functions, or anywhere else a std.object is + expected.

+ +

When making your own prototypes, derive from std.container if you want + to access the contents of your objects with the [] operator, or from + std.object if you want to access the functionality of your objects with + named object methods.

+ +

Prototype Chain

+ + +
+table
+ `-> Object
+      `-> Container
+
+ +

+ + +

Objects

+ + + + + +
std.container.ContainerContainer prototype.
+ +
+
+ + +

Objects

+ +
+
+ + std.container.Container +
+
+ Container prototype.

+ +

Container also inherits all the fields and methods from + std.object.Object. + + +

Fields:

+
    +
  • _type + string + object name + (default "Container") +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    + local std = require "std"
    + local Container = std.container {}
    +
    + local Graph = Container {
    +   _type = "Graph",
    +   _functions = {
    +     nodes = function (graph)
    +       local n = 0
    +       for _ in std.pairs (graph) do n = n + 1 end
    +       return n
    +     end,
    +   },
    + }
    + local g = Graph { "node1", "node2" }
    + --> 2
    + print (Graph.nodes (g))
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/classes/std.list.html b/classes/std.list.html new file mode 100644 index 0000000..c29ce85 --- /dev/null +++ b/classes/std.list.html @@ -0,0 +1,572 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Class std.list

+

Tables as lists.

+

+ + +

Prototype Chain

+ + +
+table
+ `-> Object
+      `-> List
+
+ +

+ + +

Objects

+ + + + + +
std.list.ListAn Object derived List.
+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
std.list.append (l, x)Append an item to a list.
std.list.compare (l, m)Compare two lists element-by-element, from left-to-right.
std.list.concat (l, ...)Concatenate the elements from any number of lists.
std.list.cons (l, x)Prepend an item to a list.
std.list.rep (l, n)Repeat a list.
std.list.sub (l[, from=1[, to=#l]])Return a sub-range of a list.
std.list.tail (l)Return a list with its first element removed.
+

Metamethods

+ + + + + + + + + + + + + + + + + +
std.list:__add (l, e)Append element to list.
std.list:__concat (l, m)Concatenate lists.
std.list:__le (l, m)List equality or order operator.
std.list:__lt (l, m)List order operator.
+ +
+
+ + +

Objects

+ +
+
+ + std.list.List +
+
+ An Object derived List. + + + + + + + +
+
+

Functions

+ Methods +
+
+ + std.list.append (l, x) +
+
+ Append an item to a list. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • x + item +
  • +
+ +

Returns:

+
    + + List + new list with x appended +
+ + + +

Usage:

+
    +
    longer = append (short, "last")
    +
+ +
+
+ + std.list.compare (l, m) +
+
+ Compare two lists element-by-element, from left-to-right. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • m + List or table + another list, or table +
  • +
+ +

Returns:

+
    + + -1 if l is less than m, 0 if they are the same, and 1 + if l is greater than m +
+ + + +

Usage:

+
    +
    if a_list:compare (another_list) == 0 then print "same" end
    +
+ +
+
+ + std.list.concat (l, ...) +
+
+ Concatenate the elements from any number of lists. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • ... + tuple of lists +
  • +
+ +

Returns:

+
    + + List + new list with elements from arguments +
+ + + +

Usage:

+
    +
    + --> {1, 2, 3, {4, 5}, 6, 7}
    + list.concat ({1, 2, 3}, {{4, 5}, 6, 7})
    +
+ +
+
+ + std.list.cons (l, x) +
+
+ Prepend an item to a list. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • x + item +
  • +
+ +

Returns:

+
    + + List + new list with x followed by elements of l +
+ + + +

Usage:

+
    +
    + --> {"x", 1, 2, 3}
    + list.cons ({1, 2, 3}, "x")
    +
+ +
+
+ + std.list.rep (l, n) +
+
+ Repeat a list. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • n + int + number of times to repeat +
  • +
+ +

Returns:

+
    + + List + n copies of l appended together +
+ + + +

Usage:

+
    +
    + --> {1, 2, 3, 1, 2, 3, 1, 2, 3}
    + list.rep ({1, 2, 3}, 3)
    +
+ +
+
+ + std.list.sub (l[, from=1[, to=#l]]) +
+
+ Return a sub-range of a list. + (The equivalent of ??? on strings; negative list indices + count from the end of the list.) + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • from + int + start of range + (default 1) +
  • +
  • to + int + end of range + (default #l) +
  • +
+ +

Returns:

+
    + + List + new list containing elements between from and to + inclusive +
+ + + +

Usage:

+
    +
    + --> {3, 4, 5}
    + list.sub ({1, 2, 3, 4, 5, 6}, 3, 5)
    +
+ +
+
+ + std.list.tail (l) +
+
+ Return a list with its first element removed. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
+ +

Returns:

+
    + + List + new list with all but the first element of l +
+ + + +

Usage:

+
    +
    + --> {3, {4, 5}, 6, 7}
    + list.tail {{1, 2}, 3, {4, 5}, 6, 7}
    +
+ +
+
+

Metamethods

+ +
+
+ + std.list:__add (l, e) +
+
+ Append element to list. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • e + element to append +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    list = list + "element"
    +
+ +
+
+ + std.list:__concat (l, m) +
+
+ Concatenate lists. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • m + List or table + another list, or table (hash part is ignored) +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    new = alist .. {"append", "these", "elements"}
    +
+ +
+
+ + std.list:__le (l, m) +
+
+ List equality or order operator. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • m + List + another list +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    min = list1 <= list2 and list1 or list2
    +
+ +
+
+ + std.list:__lt (l, m) +
+
+ List order operator. + + +

Parameters:

+
    +
  • l + List + a list +
  • +
  • m + List + another list +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    max = list1 > list2 and list1 or list2
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/classes/std.object.html b/classes/std.object.html new file mode 100644 index 0000000..65dc357 --- /dev/null +++ b/classes/std.object.html @@ -0,0 +1,511 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Class std.object

+

Prototype-based objects.

+

+ + +

This module creates the root prototype object from which every other + object is descended. There are no classes as such, rather new objects + are created by cloning an existing object, and then changing or adding + to the clone. Further objects can then be made by cloning the changed + object, and so on.

+ +

Objects are cloned by simply calling an existing object, which then + serves as a prototype from which the new object is copied.

+ +

Note that Object methods are stored in the __index field of their + metatable, and so cannot also use __index to lookup references with + square brackets. See std.container objects if you want to do that.

+ +

Prototype Chain

+ + +
+table
+ `-> Object
+
+ +

+ + +

Objects

+ + + + + +
std.object.ObjectRoot object.
+

Functions

+ + + + + + + + + + + + + +
std.object.clone (obj, ...)Clone an Object.
std.object.mapfields (obj, src[, map={}])Return obj with references to the fields of src merged in.
std.object.prototype (x)Type of an object, or primitive.
+

Metamethods

+ + + + + + + + + + + + + +
std.object:__call (...)Return a clone of this object, and its metatable.
std.object:__pairs ()Return an in-order iterator over public object fields.
std.object:__tostring ()Return a string representation of this object.
+ +
+
+ + +

Objects

+ +
+
+ + std.object.Object +
+
+ Root object.

+ +

Changing the values of these fields in a new object will change the + corresponding behaviour. + + +

Fields:

+
    +
  • _init + table or function + object initialisation + (default {}) +
  • +
  • _functions + table + module functions omitted when cloned +
  • +
  • _type + string + object name + (default "Object") +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
  • + -- `_init` can be a list of keys; then the unnamed `init_1` through
    + -- `init_m` values from the argument table are assigned to the
    + -- corresponding keys in `new_object`.
    + local Process = Object {
    +   _type = "Process",
    +   _init = { "status", "out", "err" },
    + }
    + local process = Process {
    +   procs[pid].status, procs[pid].out, procs[pid].err, -- auto assigned
    +   command = pipeline[pid],                           -- manual assignment
    + }
  • +
  • + -- Or it can be a function, in which the arguments passed to the
    + -- prototype during cloning are simply handed to the `_init` function.
    + local Bag = Object {
    +   _type = "Bag",
    +   _init = function (obj, ...)
    +     for e in std.elems {...} do
    +       obj[#obj + 1] = e
    +     end
    +     return obj
    +   end,
    + }
    + local bag = Bag ("function", "arguments", "sent", "to", "_init")
  • +
+ +
+
+

Functions

+ Methods +
+
+ + std.object.clone (obj, ...) +
+
+ Clone an Object.

+ +

Objects are essentially tables of field_n = value_n pairs.

+ +

Normally new_object automatically shares a metatable with + proto_object. However, field names beginning with "_" are private, + and moved into the object metatable during cloning. So, adding new + private fields to an object during cloning will result in a new + metatable for new_object that also happens to contain a copy of all + the entries from the proto_object metatable.

+ +

While clones of Object inherit all properties of their prototype, + it's idiomatic to always keep separate tables for the module table and + the root object itself: That way you can't mistakenly engage the slower + clone-from-module-table process unnecessarily. + + +

Parameters:

+
    +
  • obj + Object + an object +
  • +
  • ... + a list of arguments if obj._init is a function, or a + single table if obj._init is a table. +
  • +
+ +

Returns:

+
    + + Object + a clone of obj +
+ + +

See also:

+ + +

Usage:

+
    +
    + local object = require "std.object"  -- module table
    + local Object = object {}             -- root object
    + local o = Object {
    +   field_1 = "value_1",
    +   method_1 = function (self) return self.field_1 end,
    + }
    + print (o.field_1)                    --> value_1
    + o.field_2 = 2
    + function o:method_2 (n) return self.field_2 + n end
    + print (o:method_2 (2))               --> 4
    + os.exit (0)
    +
+ +
+
+ + std.object.mapfields (obj, src[, map={}]) +
+
+ Return obj with references to the fields of src merged in.

+ +

More importantly, split the fields in src between obj and its + metatable. If any field names begin with "_", attach a metatable + to obj by cloning the metatable from src, and then copy the + "private" _ prefixed fields there.

+ +

You might want to use this function to instantiate your derived + object clones when the src._init is a function -- when + src._init is a table, the default (inherited unless you overwrite + it) clone method calls mapfields automatically. When you're + using a function _init setting, clone doesn't know what to + copy into a new object from the _init function's arguments... + so you're on your own. Except that calling mapfields inside + _init is safer than manually splitting src into obj and + its metatable, because you'll pick up any fixes and changes when + you upgrade stdlib. + + +

Parameters:

+
    +
  • obj + table + destination object +
  • +
  • src + table + fields to copy int clone +
  • +
  • map + table + key renames as {old_key=new_key, ...} + (default {}) +
  • +
+ +

Returns:

+
    + + table + obj with non-private fields from src merged, + and a metatable with private fields (if any) merged, both sets + of keys renamed according to map +
+ + + +

Usage:

+
    +
    + myobject.mapfields = function (obj, src, map)
    +   object.mapfields (obj, src, map)
    +   ...
    + end
    +
+ +
+
+ + std.object.prototype (x) +
+
+ Type of an object, or primitive.

+ +

It's conventional to organise similar objects according to a + string valued _type field, which can then be queried using this + function.

+ +

Additionally, this function returns the results of ??? for + file objects, or type otherwise. + + +

Parameters:

+
    +
  • x + anything +
  • +
+ +

Returns:

+
    + + string + type of x +
+ + + +

Usage:

+
    +
    + local Stack = Object {
    +   _type = "Stack",
    +
    +   __tostring = function (self) ... end,
    +
    +   __index = {
    +     push = function (self) ... end,
    +     pop  = function (self) ... end,
    +   },
    + }
    + local stack = Stack {}
    + assert (stack:prototype () == getmetatable (stack)._type)
    +
    + local prototype = Object.prototype
    + assert (prototype (stack) == getmetatable (stack)._type)
    +
    + local h = io.open (os.tmpname (), "w")
    + assert (prototype (h) == io.type (h))
    +
    + assert (prototype {} == type {})
    +
+ +
+
+

Metamethods

+ +
+
+ + std.object:__call (...) +
+
+ Return a clone of this object, and its metatable.

+ +

Private fields are stored in the metatable. + + +

Parameters:

+
    +
  • ... + arguments for prototype's _init +
  • +
+ +

Returns:

+
    + + Object + a clone of the this object. +
+ + +

See also:

+ + +

Usage:

+
    +
    + local Object = require "std.object" {} -- not a typo!
    + new = Object {"initialisation", "elements"}
    +
+ +
+
+ + std.object:__pairs () +
+
+ Return an in-order iterator over public object fields. + + + +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + Object + self
  4. +
+ + + +

Usage:

+
    +
    for k, v in std.pairs (anobject) do process (k, v) end
    +
+ +
+
+ + std.object:__tostring () +
+
+ Return a string representation of this object.

+ +

First the object type, and then between { and } a list of the + array part of the object table (without numeric keys) followed + by the remaining key-value pairs.

+ +

This function doesn't recurse explicity, but relies upon suitable + __tostring metamethods in field values. + + + +

Returns:

+
    + + string + stringified object representation +
+ + +

See also:

+ + +

Usage:

+
    +
    print (anobject)
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/classes/std.optparse.html b/classes/std.optparse.html new file mode 100644 index 0000000..757d8dc --- /dev/null +++ b/classes/std.optparse.html @@ -0,0 +1,895 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Class std.optparse

+

Parse and process command line options.

+

+ + +

Prototype Chain

+ + +
+table
+ `-> Object
+      `-> OptionParser
+
+ +

+ + +

Objects

+ + + + + +
std.optparse.OptionParserOptionParser prototype object.
+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
std.optparse.OptionParser_Init (spec)Signature for initialising a custom OptionParser.
std.optparse.boolean (opt[, optarg="1"])Return a Lua boolean equivalent of various optarg strings.
std.optparse.file (opt, optarg)Report an option parse error unless optarg names an + existing file.
std.optparse.finished (arglist, i)Finish option processing

+ +

This is the handler automatically assigned to the option written as + -- in the OptionParser spec argument.

std.optparse.flag (arglist, i[, value])Option at arglist[i] is a boolean switch.
std.optparse.help ()Option should display help text, then exit.
std.optparse.opterr (msg)Report an option parse error, then exit with status 2.
std.optparse.optional (arglist, i[, value=true])Option at arglist[i] can take an argument.
std.optparse.required (arglist, i[, value])Option at arglist[i} requires an argument.
std.optparse.version ()Option should display version text, then exit.
+

Tables

+ + + + + + + + + +
std.optparse.boolvalsMap various option strings to equivalent Lua boolean values.
std.optparse.optsParsed options table, with a key for each encountered option, each + with value set by that option's on_handler.
+

Methods

+ + + + + + + + + + + + + +
std.optparse:on (name, handler, value)Add an option handler.
std.optparse:on_handler (arglist, i[, value=nil])Function signature of an option handler for on.
std.optparse:parse (arglist[, defaults])Parse an argument list.
+ +
+
+ + +

Objects

+ +
+
+ + std.optparse.OptionParser +
+
+ OptionParser prototype object.

+ +

Most often, after instantiating an OptionParser, everything else + is handled automatically.

+ +

Then, calling parser:parse as shown below saves unparsed arguments + into _G.arg (usually filenames or similar), and _G.opts will be a + table of successfully parsed option values. The keys into this table + are the long-options with leading hyphens stripped, and non-word + characters turned to _. For example if --another-long had been + found in the initial _G.arg, then _G.opts will have a key named + another_long, with an appropriate value. If there is no long + option name, then the short option is used, i.e. _G.opts.b will be + set.

+ +

The values saved against those keys are controlled by the option + handler, usually just true or the option argument string as + appropriate. + + +

Fields:

+
    +
  • _init + OptionParser_Init + initialisation function +
  • +
  • program + string + the first word following "Usage:" from spec +
  • +
  • version + string + the last white-space delimited word on the first line + of text from spec +
  • +
  • versiontext + string + everything preceding "Usage:" from spec, and + which will be displayed by the version on_handler +
  • +
  • helptext + string + everything including and following "Usage:" from + spec string and which will be displayed by the help + on_handler +
  • +
+ + + + +

Usage:

+
    +
    + local std = require "std"
    +
    + local optparser = std.optparse [[
    + any text VERSION
    + Additional lines of text to show when the --version
    + option is passed.
    +
    + Several lines or paragraphs are permitted.
    +
    + Usage: PROGNAME
    +
    + Banner text.
    +
    + Optional long description text to show when the --help
    + option is passed.
    +
    + Several lines or paragraphs of long description are permitted.
    +
    + Options:
    +
    +   -b                       a short option with no long option
    +       --long               a long option with no short option
    +       --another-long       a long option with internal hypen
    +   -v, --verbose            a combined short and long option
    +   -n, --dryrun, --dry-run  several spellings of the same option
    +   -u, --name=USER          require an argument
    +   -o, --output=[FILE]      accept an optional argument
    +       --version            display version information, then exit
    +       --help               display this help, then exit
    +
    + Footer text.  Several lines or paragraphs are permitted.
    +
    + Please report bugs at bug-list@yourhost.com
    + ]]
    +
    + -- Note that std.io.die and std.io.warn will only prefix messages
    + -- with `parser.program` if the parser options are assigned back to
    + -- `_G.opts`:
    + _G.arg, _G.opts = optparser:parse (_G.arg)
    +
+ +
+
+

Functions

+ Methods +
+
+ + std.optparse.OptionParser_Init (spec) +
+
+ Signature for initialising a custom OptionParser.

+ +

Read the documented options from spec and return custom parser that + can be used for parsing the options described in spec from a run-time + argument list. Options in spec are recognised as lines that begin + with at least two spaces, followed by a hyphen. + + +

Parameters:

+
    +
  • spec + string + option parsing specification +
  • +
+ +

Returns:

+
    + + OptionParser + a parser for options described by spec +
+ + + +

Usage:

+
    +
    customparser = std.optparse (optparse_spec)
    +
+ +
+
+ + std.optparse.boolean (opt[, optarg="1"]) +
+
+ Return a Lua boolean equivalent of various optarg strings. + Report an option parse error if optarg is not recognised.

+ +

Pass this as the value function to on when you want various + "truthy" or "falsey" option arguments to be coerced to a Lua true + or false respectively in the options table. + + +

Parameters:

+
    +
  • opt + string + option name +
  • +
  • optarg + string + option argument, must be a key in boolvals + (default "1") +
  • +
+ +

Returns:

+
    + + bool + true or false +
+ + + +

Usage:

+
    +
    parser:on ("--enable-nls", parser.optional, parser.boolean)
    +
+ +
+
+ + std.optparse.file (opt, optarg) +
+
+ Report an option parse error unless optarg names an + existing file.

+ +

Pass this as the value function to on when you want to accept + only option arguments that name an existing file. + + +

Parameters:

+
    +
  • opt + string + option name +
  • +
  • optarg + string + option argument, must be an existing file +
  • +
+ +

Returns:

+
    + + string + optarg +
+ + + +

Usage:

+
    +
    parser:on ("--config-file", parser.required, parser.file)
    +
+ +
+
+ + std.optparse.finished (arglist, i) +
+
+ Finish option processing

+ +

This is the handler automatically assigned to the option written as + -- in the OptionParser spec argument. You can also pass it as + the handler argument to on if you want to manually add an end + of options marker without writing it in the OptionParser spec.

+ +

This handler tells the parser to stop processing arguments, so that + anything after it will be an argument even if it otherwise looks + like an option. + + +

Parameters:

+
    +
  • arglist + table + list of arguments +
  • +
  • i + int + index of last processed element of arglist +
  • +
+ +

Returns:

+
    + + int + index of next element of arglist to process +
+ + + +

Usage:

+
    +
    parser:on ("--", parser.finished)
    +
+ +
+
+ + std.optparse.flag (arglist, i[, value]) +
+
+ Option at arglist[i] is a boolean switch.

+ +

This is the handler automatically assigned to options that have + --long-opt or -x style specifications in the OptionParser spec + argument. You can also pass it as the handler argument to on for + options you want to add manually without putting them in the + OptionParser spec.

+ +

Beware that, unlike required, this handler will store multiple + occurrences of a command-line option as a table only when given a + value function. Automatically assigned handlers do not do this, so + the option will simply be true if the option was given one or more + times on the command-line. + + +

Parameters:

+
    +
  • arglist + table + list of arguments +
  • +
  • i + int + index of last processed element of arglist +
  • +
  • value + either a function to process the option argument, + or a value to store when this flag is encountered + (optional) +
  • +
+ +

Returns:

+
    + + int + index of next element of arglist to process +
+ + + +

Usage:

+
    +
    parser:on ({"--long-opt", "-x"}, parser.flag)
    +
+ +
+
+ + std.optparse.help () +
+
+ Option should display help text, then exit.

+ +

This is the handler automatically assigned tooptions that have + --help in the specification, e.g. -h, -?, --help. + + + + + + +

Usage:

+
    +
    parser:on ("-?", parser.version)
    +
+ +
+
+ + std.optparse.opterr (msg) +
+
+ Report an option parse error, then exit with status 2.

+ +

Use this in your custom option handlers for consistency with the + error output from built-in std.optparse error messages. + + +

Parameters:

+
    +
  • msg + string + error message +
  • +
+ + + + + +
+
+ + std.optparse.optional (arglist, i[, value=true]) +
+
+ Option at arglist[i] can take an argument. + Argument is accepted only if there is a following entry that does not + begin with a '-'.

+ +

This is the handler automatically assigned to options that have + --opt=[ARG] style specifications in the OptionParser spec + argument. You can also pass it as the handler argument to on for + options you want to add manually without putting them in the + OptionParser spec.

+ +

Like required, this handler will store multiple occurrences of a + command-line option. + + +

Parameters:

+
    +
  • arglist + table + list of arguments +
  • +
  • i + int + index of last processed element of arglist +
  • +
  • value + either a function to process the option + argument, or a default value if encountered without an optarg + (default true) +
  • +
+ +

Returns:

+
    + + int + index of next element of arglist to process +
+ + + +

Usage:

+
    +
    parser:on ("--enable-nls", parser.option, parser.boolean)
    +
+ +
+
+ + std.optparse.required (arglist, i[, value]) +
+
+ +

Option at arglist[i} requires an argument.

+ +

This is the handler automatically assigned to options that have + --opt=ARG style specifications in the OptionParser spec argument. + You can also pass it as the handler argument to on for options + you want to add manually without putting them in the OptionParser + spec.

+ +

Normally the value stored in the opt table by this handler will be + the string given as the argument to that option on the command line. + However, if the option is given on the command-line multiple times, + opt["name"] will end up with all those arguments stored in the + array part of a table:

+ +
 $ cat ./prog
+ ...
+ parser:on ({"-e", "-exec"}, required)
+ _G.arg, _G.opt = parser:parse (_G.arg)
+ print std.string.tostring (_G.opt.exec)
+ ...
+ $ ./prog -e '(foo bar)' -e '(foo baz)' -- qux
+ {1=(foo bar),2=(foo baz)}
+
+ + + +

Parameters:

+
    +
  • arglist + table + list of arguments +
  • +
  • i + int + index of last processed element of arglist +
  • +
  • value + either a function to process the option argument, + or a forced value to replace the user's option argument. + (optional) +
  • +
+ +

Returns:

+
    + + int + index of next element of arglist to process +
+ + + +

Usage:

+
    +
    parser:on ({"-o", "--output"}, parser.required)
    +
+ +
+
+ + std.optparse.version () +
+
+ Option should display version text, then exit.

+ +

This is the handler automatically assigned tooptions that have + --version in the specification, e.g. -V, --version. + + + + + + +

Usage:

+
    +
    parser:on ("-V", parser.version)
    +
+ +
+
+

Tables

+ +
+
+ + std.optparse.boolvals +
+
+ Map various option strings to equivalent Lua boolean values. + + +

Fields:

+
    +
  • false + false +
  • +
  • 0 + false +
  • +
  • no + false +
  • +
  • n + false +
  • +
  • true + true +
  • +
  • 1 + true +
  • +
  • yes + true +
  • +
  • y + true +
  • +
+ + + + + +
+
+ + std.optparse.opts +
+
+ Parsed options table, with a key for each encountered option, each + with value set by that option's on_handler. Where an option + has one or more long-options specified, the key will be the first + one of those with leading hyphens stripped and non-alphanumeric + characters replaced with underscores. For options that can only be + specified by a short option, the key will be the letter of the first + of the specified short options:

+ +
 {"-e", "--eval-file"} => opts.eval_file
+ {"-n", "--dryrun", "--dry-run"} => opts.dryrun
+ {"-t", "-T"} => opts.t
+
+ +

Generally there will be one key for each previously specified + option (either automatically assigned by OptionParser or + added manually with on) containing the value(s) assigned by the + associated on_handler. For automatically assigned handlers, + that means true for straight-forward flags and + optional-argument options for which no argument was given; or else + the string value of the argument passed with an option given only + once; or a table of string values of the same for arguments given + multiple times.

+ +
 ./prog -x -n -x => opts = { x = true, dryrun = true }
+ ./prog -e '(foo bar)' -e '(foo baz)'
+     => opts = {eval_file = {"(foo bar)", "(foo baz)"} }
+
+ +

If you write your own handlers, or otherwise specify custom + handling of options with on, then whatever value those handlers + return will be assigned to the respective keys in opts. + + + + + + + +

+
+

Methods

+ +
+
+ + std.optparse:on (name, handler, value) +
+
+ Add an option handler.

+ +

When the automatically assigned option handlers don't do everything + you require, or when you don't want to put an option into the + OptionParser spec argument, use this function to specify custom + behaviour. If you write the option into the spec argument anyway, + calling this function will replace the automatically assigned handler + with your own.

+ +

When writing your own handlers for std.optparse:on, you only need + to deal with normalised arguments, because combined short arguments + (-xyz), equals separators to long options (--long=ARG) are fully + expanded before any handler is called. + + +

Parameters:

+
    +
  • name + opts + of the option, or list of option names +
  • +
  • handler + on_handler + function to call when any of opts is + encountered +
  • +
  • value + additional value passed to on_handler +
  • +
+ + + + +

Usage:

+
    +
    + -- Don't process any arguments after `--`
    + parser:on ('--', parser.finished)
    +
+ +
+
+ + std.optparse:on_handler (arglist, i[, value=nil]) +
+
+ Function signature of an option handler for on. + + +

Parameters:

+
    +
  • arglist + table + list of arguments +
  • +
  • i + int + index of last processed element of arglist +
  • +
  • value + additional value registered with on + (default nil) +
  • +
+ +

Returns:

+
    + + int + index of next element of arglist to process +
+ + + + +
+
+ + std.optparse:parse (arglist[, defaults]) +
+
+ Parse an argument list. + + +

Parameters:

+
    +
  • arglist + table + list of arguments +
  • +
  • defaults + table + table of default option values + (optional) +
  • +
+ +

Returns:

+
    +
  1. + table + a list of unrecognised arglist elements
  2. +
  3. + opts + parsing results
  4. +
+ + + + +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/classes/std.set.html b/classes/std.set.html new file mode 100644 index 0000000..0344303 --- /dev/null +++ b/classes/std.set.html @@ -0,0 +1,862 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Class std.set

+

Set container prototype.

+

+ + +

Note that Functions listed below are only available from the Set + prototype returned by requiring this module, because Container + objects cannot have object methods.

+ +

Prototype Chain

+ + +
+table
+ `-> Object
+      `-> Container
+           `-> Set
+
+ +

+ + +

Objects

+ + + + + +
std.set.SetSet prototype object.
+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
std.set.delete (set, e)Delete an element from a set.
std.set.difference (set1, set2)Find the difference of two sets.
std.set.difference (set, e)Say whether an element is in a set.
std.set.elems (set)Iterator for sets.
std.set.equal (set1, set2)Find whether two sets are equal.
std.set.insert (set, e)Insert an element into a set.
std.set.intersection (set1, set2)Find the intersection of two sets.
std.set.proper_subset (set1, set2)Find whether one set is a proper subset of another.
std.set.subset (set1, set2)Find whether one set is a subset of another.
std.set.symmetric_difference (set1, set2)Find the symmetric difference of two sets.
std.set.union (set1, set2)Find the union of two sets.
+

Metamethods

+ + + + + + + + + + + + + + + + + + + + + + + + + +
std.set.__add (set1, set2)Union operator.
std.set.__div (set1, set2)Symmetric difference operator.
std.set.__le (set1, set2)Subset operator.
std.set.__lt (set1, set2)Proper subset operator.
std.set.__mul (set1, set2)Intersection operator.
std.set.__sub (set1, set2)Difference operator.
+ +
+
+ + +

Objects

+ +
+
+ + std.set.Set +
+
+ Set prototype object.

+ +

Set also inherits all the fields and methods from + std.container.Container. + + +

Fields:

+
    +
  • _type + string + object name + (default "Set") +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    + local std = require "std"
    + std.prototype (std.set) --> "Set"
    + os.exit (0)
    +
+ +
+
+

Functions

+ Methods +
+
+ + std.set.delete (set, e) +
+
+ Delete an element from a set. + + +

Parameters:

+
    +
  • set + Set + a set +
  • +
  • e + element +
  • +
+ +

Returns:

+
    + + Set + the modified set +
+ + + +

Usage:

+
    +
    set.delete (available, found)
    +
+ +
+
+ + std.set.difference (set1, set2) +
+
+ Find the difference of two sets. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + Set + a copy of set1 with elements of set2 removed +
+ + + +

Usage:

+
    +
    all = set.difference (all, {32, 49, 56})
    +
+ +
+
+ + std.set.difference (set, e) +
+
+ Say whether an element is in a set. + + +

Parameters:

+
    +
  • set + Set + a set +
  • +
  • e + element +
  • +
+ +

Returns:

+
    + + true if e is in set, otherwise false + otherwise +
+ + + +

Usage:

+
    +
    if not set.member (keyset, pressed) then return nil end
    +
+ +
+
+ + std.set.elems (set) +
+
+ Iterator for sets. + + +

Parameters:

+
    +
  • set + Set + a set +
  • +
+ +

Returns:

+
    + + *set* + iterator +
+ + + +

Usage:

+
    +
    for code in set.elems (isprintable) do print (code) end
    +
+ +
+
+ + std.set.equal (set1, set2) +
+
+ Find whether two sets are equal. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + boolean + true if set1 and set2 each contain identical + elements, false otherwise +
+ + + +

Usage:

+
    +
    if set.equal (keys, {META, CTRL, "x"}) then process (keys) end
    +
+ +
+
+ + std.set.insert (set, e) +
+
+ Insert an element into a set. + + +

Parameters:

+
    +
  • set + Set + a set +
  • +
  • e + element +
  • +
+ +

Returns:

+
    + + Set + the modified set +
+ + + +

Usage:

+
    +
    + for byte = 32,126 do
    +   set.insert (isprintable, string.char (byte))
    + end
    +
+ +
+
+ + std.set.intersection (set1, set2) +
+
+ Find the intersection of two sets. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + Set + a new set with elements in both set1 and set2 +
+ + + +

Usage:

+
    +
    common = set.intersection (a, b)
    +
+ +
+
+ + std.set.proper_subset (set1, set2) +
+
+ Find whether one set is a proper subset of another. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + boolean + true if set2 contains all elements in set1 + but not only those elements, false otherwise +
+ + + +

Usage:

+
    +
    + if set.proper_subset (a, b) then
    +   for e in set.elems (set.difference (b, a)) do
    +     set.delete (b, e)
    +   end
    + end
    + assert (set.equal (a, b))
    +
+ +
+
+ + std.set.subset (set1, set2) +
+
+ Find whether one set is a subset of another. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + boolean + true if all elements in set1 are also in set2, + false otherwise +
+ + + +

Usage:

+
    +
    if set.subset (a, b) then a = b end
    +
+ +
+
+ + std.set.symmetric_difference (set1, set2) +
+
+ Find the symmetric difference of two sets. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + Set + a new set with elements that are in set1 or set2 + but not both +
+ + + +

Usage:

+
    +
    unique = set.symmetric_difference (a, b)
    +
+ +
+
+ + std.set.union (set1, set2) +
+
+ Find the union of two sets. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + Set + a copy of set1 with elements in set2 merged in +
+ + + +

Usage:

+
    +
    all = set.union (a, b)
    +
+ +
+
+

Metamethods

+ +
+
+ + std.set.__add (set1, set2) +
+
+ Union operator. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + Set + everything from set1 plus everything from set2 +
+ + +

See also:

+ + +

Usage:

+
    +
    union = set1 + set2
    +
+ +
+
+ + std.set.__div (set1, set2) +
+
+ Symmetric difference operator. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + Set + everything from set1 or set2 but not both +
+ + +

See also:

+ + +

Usage:

+
    +
    symmetric_difference = set1 / set2
    +
+ +
+
+ + std.set.__le (set1, set2) +
+
+ Subset operator. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + boolean + true if everything in set1 is also in set2 +
+ + +

See also:

+ + +

Usage:

+
    +
    issubset = set1 <= set2
    +
+ +
+
+ + std.set.__lt (set1, set2) +
+
+ Proper subset operator. + + +

Parameters:

+
    +
  • set1 + Set + set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + boolean + true if set2 is not equal to set1, but does + contain everything from set1 +
+ + +

See also:

+ + +

Usage:

+
    +
    ispropersubset = set1 < set2
    +
+ +
+
+ + std.set.__mul (set1, set2) +
+
+ Intersection operator. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + Set + anything this is in both set1 and set2 +
+ + +

See also:

+ + +

Usage:

+
    +
    intersection = set1 * set2
    +
+ +
+
+ + std.set.__sub (set1, set2) +
+
+ Difference operator. + + +

Parameters:

+
    +
  • set1 + Set + a set +
  • +
  • set2 + Set + another set +
  • +
+ +

Returns:

+
    + + Set + everything from set1 that is not also in set2 +
+ + +

See also:

+ + +

Usage:

+
    +
    difference = set1 - set2
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/classes/std.strbuf.html b/classes/std.strbuf.html new file mode 100644 index 0000000..22c5c94 --- /dev/null +++ b/classes/std.strbuf.html @@ -0,0 +1,298 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Class std.strbuf

+

String buffers.

+

+ + +

Buffers are mutable by default, but being based on objects, they can + also be used in a functional style:

+ + +
+local StrBuf = require "std.strbuf" {}
+local a = StrBuf {"a"}
+local b = a:concat "b"    -- mutate *a*
+print (a, b)              --> ab   ab
+local c = a {} .. "c"     -- copy and append
+print (a, c)              --> ab   abc
+
+
+ +

Prototype Chain

+ + +
+table
+ `-> Object
+      `-> StrBuf
+
+ +

+ + +

Objects

+ + + + + +
std.strbuf.StrBufStrBuf prototype object.
+

Functions

+ + + + + +
std.strbuf.concat (x)Add a object to a buffer.
+

Metamethods

+ + + + + + + + + +
std.strbuf:__concat (buffer, x)Support concatenation to StrBuf objects.
std.strbuf:__tostring (buffer)Support fast conversion to Lua string.
+ +
+
+ + +

Objects

+ +
+
+ + std.strbuf.StrBuf +
+
+ StrBuf prototype object.

+ +

Set also inherits all the fields and methods from + std.object.Object. + + +

Fields:

+
    +
  • _type + string + object name + (default "StrBuf") +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    + local std = require "std"
    + local StrBuf = std.strbuf {}
    + local a = {1, 2, 3}
    + local b = {a, "five", "six"}
    + a = a .. 4
    + b = b:concat "seven"
    + print (a, b) --> 1234   1234fivesixseven
    + os.exit (0)
    +
+ +
+
+

Functions

+ Methods +
+
+ + std.strbuf.concat (x) +
+
+ Add a object to a buffer. + Elements are stringified lazily, so if add a table and then change + its contents, the contents of the buffer will be affected too. + + +

Parameters:

+
    +
  • x + object to add to buffer +
  • +
+ +

Returns:

+
    + + StrBuf + modified buffer +
+ + + +

Usage:

+
    +
    buf = buf:concat "append this" {" and", " this"}
    +
+ +
+
+

Metamethods

+ +
+
+ + std.strbuf:__concat (buffer, x) +
+
+ Support concatenation to StrBuf objects. + + +

Parameters:

+
    +
  • buffer + StrBuf + object +
  • +
  • x + a string, or object that can be coerced to a string +
  • +
+ +

Returns:

+
    + + StrBuf + modified buf +
+ + +

See also:

+ + +

Usage:

+
    +
    buf = buf .. x
    +
+ +
+
+ + std.strbuf:__tostring (buffer) +
+
+ Support fast conversion to Lua string. + + +

Parameters:

+
    +
  • buffer + StrBuf + object +
  • +
+ +

Returns:

+
    + + string + concatenation of buffer contents +
+ + +

See also:

+ + +

Usage:

+
    +
    str = tostring (buf)
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/classes/std.tree.html b/classes/std.tree.html new file mode 100644 index 0000000..0a64c23 --- /dev/null +++ b/classes/std.tree.html @@ -0,0 +1,545 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Class std.tree

+

Tree container prototype.

+

+ + +

Note that Functions listed below are only available from the Tree + prototype returned by requiring this module, because Container objects + cannot have object methods.

+ +

Prototype Chain

+ + +
+table
+ `-> Object
+      `-> Container
+           `-> Tree
+
+ +

+ + +

Objects

+ + + + + +
std.tree.TreeTree prototype object.
+

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + +
std.tree.clone (t, nometa)Make a deep copy of a tree, including any metatables.
std.tree.ileaves (tr)Tree iterator which returns just numbered leaves, in order.
std.tree.inodes (tr)Tree iterator over numbered nodes, in order.
std.tree.leaves (t)Tree iterator which returns just leaves.
std.tree.merge (t, u)Destructively deep-merge one tree into another.
std.tree.nodes (tr)Tree iterator over all nodes.
+

Metamethods

+ + + + + + + + + +
std.tree.__index (tr, i)Deep retrieval.
std.tree.__newindex (tr, i[, v])Deep insertion.
+ +
+
+ + +

Objects

+ +
+
+ + std.tree.Tree +
+
+ Tree prototype object. + + +

Fields:

+
    +
  • _type + string + object name + (default "Tree") +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    + local std = require "std"
    + local Tree = std.tree {}
    + local tr = Tree {}
    + tr[{"branch1", 1}] = "leaf1"
    + tr[{"branch1", 2}] = "leaf2"
    + tr[{"branch2", 1}] = "leaf3"
    + print (tr[{"branch1"}])      --> Tree {leaf1, leaf2}
    + print (tr[{"branch1", 2}])   --> leaf2
    + print (tr[{"branch1", 3}])   --> nil
    + --> leaf1	leaf2	leaf3
    + for leaf in std.tree.leaves (tr) do
    +   io.write (leaf .. "\t")
    + end
    +
+ +
+
+

Functions

+ Methods +
+
+ + std.tree.clone (t, nometa) +
+
+ Make a deep copy of a tree, including any metatables. + + +

Parameters:

+
    +
  • t + table + tree or tree-like table +
  • +
  • nometa + boolean + if non-nil don't copy metatables +
  • +
+ +

Returns:

+
    + + Tree or table + a deep copy of tr +
+ + +

See also:

+ + +

Usage:

+
    +
    + tr = {"one", {two=2}, {{"three"}, four=4}}
    + copy = clone (tr)
    + copy[2].two=5
    + assert (tr[2].two == 2)
    +
+ +
+
+ + std.tree.ileaves (tr) +
+
+ Tree iterator which returns just numbered leaves, in order. + + +

Parameters:

+
    +
  • tr + Tree or table + tree or tree-like table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + Tree or table + the tree tr
  4. +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> t = {"one", "three", "five"}
    + for leaf in ileaves {"one", {two=2}, {{"three"}, four=4}}, foo="bar", "five"}
    + do
    +   t[#t + 1] = leaf
    + end
    +
+ +
+
+ + std.tree.inodes (tr) +
+
+ Tree iterator over numbered nodes, in order.

+ +

The iterator function behaves like nodes, but only traverses the + array part of the nodes of tr, ignoring any others. + + +

Parameters:

+
    +
  • tr + Tree or table + tree or tree-like table to iterate over +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + tree or table + the tree, tr
  4. +
+ + +

See also:

+ + + +
+
+ + std.tree.leaves (t) +
+
+ Tree iterator which returns just leaves. + + +

Parameters:

+
    +
  • t + table + tree or tree-like table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + table + t
  4. +
+ + +

See also:

+ + +

Usage:

+
    +
    + for leaf in leaves {"one", {two=2}, {{"three"}, four=4}}, foo="bar", "five"}
    + do
    +   t[#t + 1] = leaf
    + end
    + --> t = {2, 4, "five", "foo", "one", "three"}
    + table.sort (t, lambda "=tostring(_1) < tostring(_2)")
    +
+ +
+
+ + std.tree.merge (t, u) +
+
+ Destructively deep-merge one tree into another. + + +

Parameters:

+
    +
  • t + table + destination tree +
  • +
  • u + table + table with nodes to merge +
  • +
+ +

Returns:

+
    + + table + t with nodes from u merged in +
+ + +

See also:

+ + +

Usage:

+
    +
    merge (dest, {{exists=1}, {{not = {present = { inside = "dest" }}}}})
    +
+ +
+
+ + std.tree.nodes (tr) +
+
+ Tree iterator over all nodes.

+ +

The returned iterator function performs a depth-first traversal of + tr, and at each node it returns {node-type, tree-path, tree-node} + where node-type is branch, join or leaf; tree-path is a + list of keys used to reach this node, and tree-node is the current + node.

+ +

Note that the tree-path reuses the same table on each iteration, so + you must table.clone a copy if you want to take a snap-shot of the + current state of the tree-path list before the next iteration + changes it. + + +

Parameters:

+
    +
  • tr + Tree or table + tree or tree-like table to iterate over +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + Tree or table + the tree, tr
  4. +
+ + +

See also:

+ + +

Usage:

+
    +
    + -- tree = +-- node1
    + --        |    +-- leaf1
    + --        |    '-- leaf2
    + --        '-- leaf 3
    + tree = Tree { Tree { "leaf1", "leaf2"}, "leaf3" }
    + for node_type, path, node in nodes (tree) do
    +   print (node_type, path, node)
    + end
    + --> "branch"   {}      {{"leaf1", "leaf2"}, "leaf3"}
    + --> "branch"   {1}     {"leaf1", "leaf"2")
    + --> "leaf"     {1,1}   "leaf1"
    + --> "leaf"     {1,2}   "leaf2"
    + --> "join"     {1}     {"leaf1", "leaf2"}
    + --> "leaf"     {2}     "leaf3"
    + --> "join"     {}      {{"leaf1", "leaf2"}, "leaf3"}
    + os.exit (0)
    +
+ +
+
+

Metamethods

+ +
+
+ + std.tree.__index (tr, i) +
+
+ Deep retrieval. + + +

Parameters:

+
    +
  • tr + Tree + a tree +
  • +
  • i + non-table, or list of keys {i1, ...i_n} +
  • +
+ +

Returns:

+
    + + tr[i1]...[i_n] if i is a key list, tr[i] otherwise +
+ + + +

Usage:

+
    +
    del_other_window = keymap[{"C-x", "4", KEY_DELETE}]
    +
+ +
+
+ + std.tree.__newindex (tr, i[, v]) +
+
+ Deep insertion. + + +

Parameters:

+
    +
  • tr + Tree + a tree +
  • +
  • i + non-table, or list of keys {i1, ...i_n} +
  • +
  • v + value + (optional) +
  • +
+ + + + +

Usage:

+
    +
    function bindkey (keylist, fn) keymap[keylist] = fn end
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/index.html b/index.html new file mode 100644 index 0000000..9a1556f --- /dev/null +++ b/index.html @@ -0,0 +1,146 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ + +

Standard Lua Libraries

+ +

Modules

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
stdLua Standard Libraries.
std.debugAdditions to the core debug module.
std.functionalFunctional programming.
std.ioAdditions to the core io module.
std.mathAdditions to the core math module.
std.operatorFunctional forms of Lua operators.
std.packageAdditions to the core package module.
std.strictChecks uses of undeclared global variables.
std.stringAdditions to the core string module.
std.tableExtensions to the core table module.
+

Classes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
std.treeTree container prototype.
std.containerContainer prototype.
std.objectPrototype-based objects.
std.listTables as lists.
std.optparseParse and process command line options.
std.setSet container prototype.
std.strbufString buffers.
+ +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/ldoc.css b/ldoc.css new file mode 100644 index 0000000..7d74ca2 --- /dev/null +++ b/ldoc.css @@ -0,0 +1,307 @@ +/* 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 { + list-style: disc; + 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.example { + background-color: rgb(245, 245, 245); + border: 1px solid silver; + padding: 10px; + margin: 10px 0 10px 0; + font-family: "Andale Mono", monospace; + font-size: .85em; +} + +pre { + background-color: rgb(245, 245, 245); + border: 1px solid silver; + padding: 10px; + margin: 10px 0 10px 0; + overflow: auto; + font-family: "Andale Mono", monospace; +} + + +table.index { border: 1px #00007f; } +table.index td { text-align: left; vertical-align: top; } + +#container { + margin-left: 1em; + margin-right: 1em; + background-color: #f0f0f0; +} + +#product { + text-align: center; + border-bottom: 1px solid #cccccc; + background-color: #ffffff; +} + +#product big { + font-size: 2em; +} + +#main { + background-color: #f0f0f0; + border-left: 2px solid #cccccc; +} + +#navigation { + float: left; + width: 14em; + vertical-align: top; + background-color: #f0f0f0; + overflow: visible; +} + +#navigation h2 { + background-color:#e7e7e7; + font-size:1.1em; + color:#000000; + text-align: left; + padding:0.2em; + border-top:1px solid #dddddd; + 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; + width: 700px; + border-left: 2px solid #cccccc; + border-right: 2px solid #cccccc; + background-color: #ffffff; +} + +#about { + clear: both; + padding: 5px; + border-top: 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: #f0f0f0; min-width: 200px; } +table.function_list td.summary { width: 100%; } + +ul.nowrap { + overflow:auto; + white-space:nowrap; +} + +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;} + +/* 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 .prompt { color: #558817; } +pre .url { color: #272fc2; text-decoration: underline; } diff --git a/lib/std/_base.lua b/lib/std/_base.lua deleted file mode 100644 index 0c623d4..0000000 --- a/lib/std/_base.lua +++ /dev/null @@ -1,204 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Prevent dependency loops with key function implementations. - - A few key functions are used in several stdlib modules; we implement those - functions in this internal module to prevent dependency loops in the first - instance, and to minimise coupling between modules where the use of one of - these functions might otherwise load a whole selection of other supporting - modules unnecessarily. - - Although the implementations are here for logistical reasons, we re-export - them from their respective logical modules so that the api is not affected - as far as client code is concerned. The functions in this file do not make - use of `argcheck` or similar, because we know that they are only called by - other stdlib functions which have already performed the necessary checking - and neither do we want to slow everything down by recheckng those argument - types here. - - This implies that when re-exporting from another module when argument type - checking is in force, we must export a wrapper function that can check the - user's arguments fully at the API boundary. -]] - - -local _ENV = require 'std.normalize' { - concat = 'table.concat', - dirsep = 'package.dirsep', - find = 'string.find', - gsub = 'string.gsub', - insert = 'table.insert', - min = 'math.min', - shallow_copy = 'table.merge', - sort = 'table.sort', - sub = 'string.sub', - table_maxn = table.maxn, - wrap = 'coroutine.wrap', - yield = 'coroutine.yield', -} - - - ---[[ ============================ ]]-- ---[[ Enhanced Core Lua functions. ]]-- ---[[ ============================ ]]-- - - --- These come as early as possible, because we want the rest of the code --- in this file to use these versions over the core Lua implementation --- (which have slightly varying semantics between releases). - - -local maxn = table_maxn or function(t) - local n = 0 - for k in pairs(t) do - if type(k) == 'number' and k > n then - n = k - end - end - return n -end - - - ---[[ ============================ ]]-- ---[[ Shared Stdlib API functions. ]]-- ---[[ ============================ ]]-- - - --- No need to recurse because functables are second class citizens in --- Lua: --- func = function() print 'called' end --- func() --> 'called' --- functable=setmetatable({}, {__call=func}) --- functable() --> 'called' --- nested=setmetatable({}, {__call=functable}) --- nested() --- --> stdin:1: attempt to call a table value(global 'd') --- --> stack traceback: --- --> stdin:1: in main chunk --- --> [C]: in ? -local function callable(x) - if type(x) == 'function' then - return x - end - return (getmetatable(x) or {}).__call -end - - -local function catfile(...) - return concat({...}, dirsep) -end - - -local function compare(l, m) - local lenl, lenm = len(l), len(m) - for i = 1, min(lenl, lenm) do - local li, mi = tonumber(l[i]), tonumber(m[i]) - if li == nil or mi == nil then - li, mi = l[i], m[i] - end - if li < mi then - return -1 - elseif li > mi then - return 1 - end - end - if lenl < lenm then - return -1 - elseif lenl > lenm then - return 1 - end - return 0 -end - - -local function escape_pattern(s) - return (gsub(s, '[%^%$%(%)%%%.%[%]%*%+%-%?]', '%%%0')) -end - - -local function invert(t) - local i = {} - for k, v in pairs(t) do - i[v] = k - end - return i -end - - -local function leaves(it, tr) - local function visit(n) - if type(n) == 'table' then - for _, v in it(n) do - visit(v) - end - else - yield(n) - end - end - return wrap(visit), tr -end - - -local function split(s, sep) - local r, patt = {} - if sep == '' then - patt = '(.)' - insert(r, '') - else - patt = '(.-)' ..(sep or '%s+') - end - local b, slen = 0, len(s) - while b <= slen do - local e, n, m = find(s, patt, b + 1) - insert(r, m or sub(s, b + 1, slen)) - b = n or slen + 1 - end - return r -end - - ---[[ ============= ]]-- ---[[ Internal API. ]]-- ---[[ ============= ]]-- - - --- For efficient use within stdlib, these functions have no type-checking. --- In debug mode, type-checking wrappers are re-exported from the public- --- facing modules as necessary. --- --- Also, to provide some sanity, we mirror the subtable layout of stdlib --- public API here too, which means everything looks relatively normal --- when importing the functions into stdlib implementation modules. -return { - io = { - catfile = catfile, - }, - - list = { - compare = compare, - }, - - object = { - Module = Module, - mapfields = mapfields, - }, - - string = { - escape_pattern = escape_pattern, - split = split, - }, - - table = { - invert = invert, - maxn = maxn, - }, - - tree = { - leaves = leaves, - }, -} diff --git a/lib/std/debug.lua b/lib/std/debug.lua deleted file mode 100644 index cab29ff..0000000 --- a/lib/std/debug.lua +++ /dev/null @@ -1,156 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core debug module. - - The module table returned by `std.debug` also contains all of the entries - from the core debug table. An hygienic way to import this module, then, is - simply to override the core `debug` locally: - - local debug = require 'std.debug' - - @corelibrary std.debug -]] - - -local _ENV = require 'std.normalize' { - 'debug', - _debug = require 'std._debug', - concat = 'table.concat', - huge = 'math.huge', - max = 'math.max', - merge = 'table.merge', - stderr = 'io.stderr', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local function say(n, ...) - local level, argt = n, {...} - if type(n) ~= 'number' then - level, argt = 1, {n, ...} - end - if _debug.level ~= huge and - ((type(_debug.level) == 'number' and _debug.level >= level) or level <= 1) - then - local t = {} - for k, v in pairs(argt) do - t[k] = str(v) - end - stderr:write(concat(t, '\t') .. '\n') - end -end - - -local level = 0 - -local function trace(event) - local t = debug.getinfo(3) - local s = ' >>> ' - for i = 1, level do - s = s .. ' ' - end - if t ~= nil and t.currentline >= 0 then - s = s .. t.short_src .. ':' .. t.currentline .. ' ' - end - t = debug.getinfo(2) - if event == 'call' then - level = level + 1 - else - level = max(level - 1, 0) - end - if t.what == 'main' then - if event == 'call' then - s = s .. 'begin ' .. t.short_src - else - s = s .. 'end ' .. t.short_src - end - elseif t.what == 'Lua' then - s = s .. event .. ' ' ..(t.name or '(Lua)') .. ' <' .. - t.linedefined .. ':' .. t.short_src .. '>' - else - s = s .. event .. ' ' ..(t.name or '(C)') .. ' [' .. t.what .. ']' - end - stderr:write(s .. '\n') -end - --- Set hooks according to _debug -if _debug.call then - debug.sethook(trace, 'cr') -end - - - -local M = { - --- Function Environments - -- @section environments - - --- Extend `debug.getfenv` to unwrap functables correctly. - -- @function getfenv - -- @tparam int|function|functable fn target function, or stack level - -- @treturn table environment of *fn* - getfenv = getfenv, - - --- Extend `debug.setfenv` to unwrap functables correctly. - -- @function setfenv - -- @tparam function|functable fn target function - -- @tparam table env new function environment - -- @treturn function *fn* - setfenv = setfenv, - - - --- Functions - -- @section functions - - --- Print a debugging message to `io.stderr`. - -- Display arguments passed through `std.tostring` and separated by tab - -- characters when `std._debug` hinting is `true` and *n* is 1 or less; - -- or `std._debug.level` is a number greater than or equal to *n*. If - -- `std._debug` hinting is false or nil, nothing is written. - -- @function say - -- @int[opt=1] n debugging level, smaller is higher priority - -- @param ... objects to print(as for print) - -- @usage - -- local _debug = require 'std._debug' - -- _debug.level = 3 - -- say(2, '_debug status level:', _debug.level) - say = say, - - --- Trace function calls. - -- Use as debug.sethook(trace, 'cr'), which is done automatically - -- when `std._debug.call` is set. - -- Based on test/trace-calls.lua from the Lua distribution. - -- @function trace - -- @string event event causing the call - -- @usage - -- local _debug = require 'std._debug' - -- _debug.call = true - -- local debug = require 'std.debug' - trace = trace, -} - - ---- Metamethods --- @section metamethods - ---- Equivalent to calling `debug.say(1, ...)` --- @function __call --- @see say --- @usage --- local debug = require 'std.debug' --- debug 'oh noes!' -local metatable = { - __call = function(self, ...) - M.say(1, ...) - end, -} - - -return setmetatable(merge(debug, M), metatable) diff --git a/lib/std/init.lua b/lib/std/init.lua deleted file mode 100644 index 732d41f..0000000 --- a/lib/std/init.lua +++ /dev/null @@ -1,389 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Enhanced Lua core functions, and others. - - After requiring this module, simply referencing symbols in the submodule - hierarchy will load the necessary modules on demand. There are no - changes to any global symbols, or monkey patching of core module tables - and metatables. - - @todo Write a style guide(indenting/wrapping, capitalisation, - function and variable names); library functions should call - error, not die; OO vs non-OO(a thorny problem). - @todo pre-compile. - @corefunction std -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck -local compare = _.list.compare -local maxn = _.table.maxn -local split = _.string.split - -_ = nil - - -local _ENV = require 'std.normalize' { - format = 'string.format', - match = 'string.match', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local M - - -local function _assert(expect, fmt, arg1, ...) - local msg =(arg1 ~= nil) and format(fmt, arg1, ...) or fmt or '' - return expect or error(msg, 2) -end - - -local function elems(t) - -- capture pairs iterator initial state - local fn, istate, ctrl = pairs(t) - return function(state, _) - local v - ctrl, v = fn(state, ctrl) - if ctrl then - return v - end - end, istate, true -- wrapped initial state -end - - -local function eval(s) - return load('return ' .. s)() -end - - -local function ielems(t) - -- capture pairs iterator initial state - local fn, istate, ctrl = ipairs(t) - return function(state, _) - local v - ctrl, v = fn(state, ctrl) - if ctrl then - return v - end - end, istate, true -- wrapped initial state -end - - -local function npairs(t) - local m = getmetamethod(t, '__len') - local i, n = 0, m and m(t) or maxn(t) - return function(t) - i = i + 1 - if i <= n then - return i, t[i] - end - end, - t, i -end - - -local function ripairs(t) - local oob = 1 - while t[oob] ~= nil do - oob = oob + 1 - end - - return function(t, n) - n = n - 1 - if n > 0 then - return n, t[n] - end - end, t, oob -end - - -local function rnpairs(t) - local m = getmetamethod(t, '__len') - local oob =(m and m(t) or maxn(t)) + 1 - - return function(t, n) - n = n - 1 - if n > 0 then - return n, t[n] - end - end, t, oob -end - - -local vconvert = setmetatable({ - string = function(x) - return split(x, '%.') - end, - number = function(x) - return {x} - end, - table = function(x) - return x - end, -}, { - __call = function(self, x) - local fn = self[type(x)] or function() - return 0 - end - return fn(x) - end, -}) - - -local function vcompare(a, b) - return compare(vconvert(a), vconvert(b)) -end - - -local function _require(module, min, too_big, pattern) - pattern = pattern or '([%.%d]+)%D*$' - - local s, m = '', require(module) - if type(m) == 'table' then - s = tostring(m.version or m._VERSION or '') - end - local v = match(s, pattern) or 0 - if min then - _assert(vcompare(v, min) >= 0, "require '" .. module .. - "' with at least version " .. min .. ', but found version ' .. v) - end - if too_big then - _assert(vcompare(v, too_big) < 0, "require '" .. module .. - "' with version less than " .. too_big .. ', but found version ' .. v) - end - return m -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.' .. decl, fn) or fn -end - -M = { - --- Release version string. - -- @field version - - - --- Core Functions - -- @section corefuncs - - --- Enhance core `assert` to also allow formatted arguments. - -- @function assert - -- @param expect expression, expected to be *truthy* - -- @string[opt=''] f format string - -- @param[opt] ... arguments to format - -- @return value of *expect*, if *truthy* - -- @usage - -- std.assert(expect == nil, '100% unexpected!') - -- std.assert(expect == 'expect', '%s the unexpected!', expect) - assert = X('assert(?any, ?string, [any...])', _assert), - - --- Evaluate a string as Lua code. - -- @function eval - -- @string s string of Lua code - -- @return result of evaluating `s` - -- @usage - -- --> 2 - -- std.eval 'math.min(2, 10)' - eval = X('eval(string)', eval), - - --- Return named metamethod, if any, otherwise `nil`. - -- The value found at the given key in the metatable of *x* must be a - -- function or have its own `__call` metamethod to qualify as a - -- callable. Any other value found at key *n* will cause this function - -- to return `nil`. - -- @function getmetamethod - -- @param x item to act on - -- @string n name of metamethod to lookup - -- @treturn callable|nil callable metamethod, or `nil` if no metamethod - -- @usage - -- clone = std.getmetamethod(std.object.prototype, '__call') - getmetamethod = X('getmetamethod(?any, string)', getmetamethod), - - - --- Module Functions - -- @section modulefuncs - - --- Enhance core `require` to assert version number compatibility. - -- By default match against the last substring of(dot-delimited) - -- digits in the module version string. - -- @function require - -- @string module module to require - -- @string[opt] min lowest acceptable version - -- @string[opt] too_big lowest version that is too big - -- @string[opt] pattern to match version in `module.version` or - -- `module._VERSION`(default: `'([%.%d]+)%D*$'`) - -- @usage - -- -- posix.version == 'posix library for Lua 5.2 / 32' - -- posix = require('posix', '29') - require = X('require(string, ?string, ?string, ?string)', _require), - - --- Iterator Functions - -- @section iteratorfuncs - - --- An iterator over all values of a table. - -- If *t* has a `__pairs` metamethod, use that to iterate. - -- @function elems - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @return *key*, the previous iteration key - -- @see ielems - -- @see pairs - -- @usage - -- --> foo - -- --> bar - -- --> baz - -- --> 5 - -- std.functional.map(print, std.ielems, {'foo', 'bar', [4]='baz', d=5}) - elems = X('elems(table)', elems), - - --- An iterator over the integer keyed elements of a table. - -- - -- If *t* has a `__len` metamethod, iterate up to the index it - -- returns, otherwise up to the first `nil`. - -- - -- This function does **not** support the Lua 5.2 `__ipairs` metamethod. - -- @function ielems - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @treturn int *index*, the previous iteration index - -- @see elems - -- @see ipairs - -- @usage - -- --> foo - -- --> bar - -- std.functional.map(print, std.ielems, {'foo', 'bar', [4]='baz', d=5}) - ielems = X('ielems(table)', ielems), - - --- An iterator over integer keyed pairs of a sequence. - -- - -- Like Lua 5.1 and 5.3, this iterator returns successive key-value - -- pairs with integer keys starting at 1, up to the first `nil` valued - -- pair. - -- - -- If there is a `_len` metamethod, keep iterating up to and including - -- that element, regardless of any intervening `nil` values. - -- - -- This function does **not** support the Lua 5.2 `__ipairs` metamethod. - -- @function ipairs - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @treturn int *index*, the previous iteration index - -- @see ielems - -- @see npairs - -- @see pairs - -- @usage - -- --> 1 foo - -- --> 2 bar - -- std.functional.map(print, std.ipairs, {'foo', 'bar', [4]='baz', d=5}) - ipairs = X('ipairs(table)', ipairs), - - --- Ordered iterator for integer keyed values. - -- Like ipairs, but does not stop until the __len or maxn of *t*. - -- @function npairs - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table t - -- @see ipairs - -- @see rnpairs - -- @usage - -- --> 1 foo - -- --> 2 bar - -- --> 3 nil - -- --> 4 baz - -- std.functional.map(print, std.npairs, {'foo', 'bar', [4]='baz', d=5}) - npairs = X('npairs(table)', npairs), - - --- Enhance core `pairs` to respect `__pairs` even in Lua 5.1. - -- @function pairs - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table *t*, the table being iterated over - -- @return *key*, the previous iteration key - -- @see elems - -- @see ipairs - -- @usage - -- --> 1 foo - -- --> 2 bar - -- --> 4 baz - -- --> d 5 - -- std.functional.map(print, std.pairs, {'foo', 'bar', [4]='baz', d=5}) - pairs = X('pairs(table)', pairs), - - --- An iterator like ipairs, but in reverse. - -- Apart from the order of the elements returned, this function follows - -- the same rules as @{ipairs} for determining first and last elements. - -- @function ripairs - -- @tparam table t any table - -- @treturn function iterator function - -- @treturn table *t* - -- @treturn number `#t + 1` - -- @see ipairs - -- @see rnpairs - -- @usage - -- --> 2 bar - -- --> 1 foo - -- std.functional.map(print, std.ripairs, {'foo', 'bar', [4]='baz', d=5}) - ripairs = X('ripairs(table)', ripairs), - - --- An iterator like npairs, but in reverse. - -- Apart from the order of the elements returned, this function follows - -- the same rules as @{npairs} for determining first and last elements. - -- @function rnpairs - -- @tparam table t a table - -- @treturn function iterator function - -- @treturn table t - -- @see npairs - -- @see ripairs - -- @usage - -- --> 4 baz - -- --> 3 nil - -- --> 2 bar - -- --> 1 foo - -- std.functional.map(print, std.rnpairs, {'foo', 'bar', [4]='baz', d=5}) - rnpairs = X('rnpairs(table)', rnpairs), -} - - ---- Metamethods --- @section Metamethods - -return setmetatable(M, { - --- Lazy loading of stdlib modules. - -- Don't load everything on initial startup, wait until first attempt - -- to access a submodule, and then load it on demand. - -- @function __index - -- @string name submodule name - -- @treturn table|nil the submodule that was loaded to satisfy the missing - -- `name`, otherwise `nil` if nothing was found - -- @usage - -- local std = require 'std' - -- local Object = std.object.prototype - __index = function(self, name) - local ok, t = pcall(require, 'std.' .. name) - if ok then - rawset(self, name, t) - return t - end - end, -}) diff --git a/lib/std/io.lua b/lib/std/io.lua deleted file mode 100644 index 1a2b79f..0000000 --- a/lib/std/io.lua +++ /dev/null @@ -1,322 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core io module. - - The module table returned by `std.io` also contains all of the entries from - the core `io` module table. An hygienic way to import this module, then, - is simply to override core `io` locally: - - local io = require 'std.io' - - @corelibrary std.io -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck -local catfile = _.io.catfile -local leaves = _.tree.leaves -local split = _.string.split - -_ = nil - - -local _ENV = require 'std.normalize' { - 'io', - _G = _G, -- FIXME: don't use the host _G as an API! - concat = 'table.concat', - dirsep = 'package.dirsep', - format = 'string.format', - gsub = 'string.gsub', - input = 'io.input', - insert = 'table.insert', - io_type = 'io.type', - merge = 'table.merge', - open = 'io.open', - output = 'io.output', - popen = 'io.popen', - stderr = 'io.stderr', - stdin = 'io.stdin', - write = 'io.write', -} - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local M - - -local function input_handle(h) - if h == nil then - return input() - elseif type(h) == 'string' then - return open(h) - end - return h -end - - -local function slurp(file) - local h, err = input_handle(file) - if h == nil then - argerror('std.io.slurp', 1, err, 2) - end - - if h then - local s = h:read('*a') - h:close() - return s - end -end - - -local function readlines(file) - local h, err = input_handle(file) - if h == nil then - argerror('std.io.readlines', 1, err, 2) - end - - local l = {} - for line in h:lines() do - l[#l + 1] = line - end - h:close() - return l -end - - -local function writelines(h, ...) - if io_type(h) ~= 'file' then - write(h, '\n') - h = output() - end - for v in leaves(ipairs, {...}) do - h:write(v, '\n') - end -end - - -local function process_files(fn) - -- N.B. 'arg' below refers to the global array of command-line args - if len(arg) == 0 then - insert(arg, '-') - end - for i, v in ipairs(arg) do - if v == '-' then - input(stdin) - else - input(v) - end - fn(v, i) - end -end - - -local function warnfmt(msg, ...) - local prefix = '' - local prog = rawget(_G, 'prog') or {} - local opts = rawget(_G, 'opts') or {} - if prog.name then - prefix = prog.name .. ':' - if prog.line then - prefix = prefix .. str(prog.line) .. ':' - end - elseif prog.file then - prefix = prog.file .. ':' - if prog.line then - prefix = prefix .. str(prog.line) .. ':' - end - elseif opts.program then - prefix = opts.program .. ':' - if opts.line then - prefix = prefix .. str(opts.line) .. ':' - end - end - if #prefix > 0 then - prefix = prefix .. ' ' - end - return prefix .. format(msg, ...) -end - - -local function warn(msg, ...) - writelines(stderr, warnfmt(msg, ...)) -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.io.' .. decl, fn) or fn -end - - -M = { - --- Diagnostic functions - -- @section diagnosticfuncs - - --- Die with error. - -- This function uses the same rules to build a message prefix - -- as @{warn}. - -- @function die - -- @string msg format string - -- @param ... additional arguments to plug format string specifiers - -- @see warn - -- @usage - -- die('oh noes!(%s)', tostring(obj)) - die = X('die(string, [any...])', function(...) - error(warnfmt(...), 0) - end), - - --- Give warning with the name of program and file(if any). - -- If there is a global `prog` table, prefix the message with - -- `prog.name` or `prog.file`, and `prog.line` if any. Otherwise - -- if there is a global `opts` table, prefix the message with - -- `opts.program` and `opts.line` if any. - -- @function warn - -- @string msg format string - -- @param ... additional arguments to plug format string specifiers - -- @see die - -- @usage - -- local OptionParser = require 'std.optparse' - -- local parser = OptionParser 'eg 0\nUsage: eg\n' - -- _G.arg, _G.opts = parser:parse(_G.arg) - -- if not _G.opts.keep_going then - -- require 'std.io'.warn 'oh noes!' - -- end - warn = X('warn(string, [any...])', warn), - - - --- Path Functions - -- @section pathfuncs - - --- Concatenate directory names into a path. - -- @function catdir - -- @string ... path components - -- @return path without trailing separator - -- @see catfile - -- @usage - -- dirpath = catdir('', 'absolute', 'directory') - catdir = X('catdir(string...)', function(...) - return(gsub(concat({...}, dirsep), '^$', dirsep)) - end), - - --- Concatenate one or more directories and a filename into a path. - -- @function catfile - -- @string ... path components - -- @treturn string path - -- @see catdir - -- @see splitdir - -- @usage - -- filepath = catfile('relative', 'path', 'filename') - catfile = X('catfile(string...)', catfile), - - --- Remove the last dirsep delimited element from a path. - -- @function dirname - -- @string path file path - -- @treturn string a new path with the last dirsep and following - -- truncated - -- @usage - -- dir = dirname '/base/subdir/filename' - dirname = X('dirname(string)', function(path) - return(gsub(path, catfile('', '[^', ']*$'), '')) - end), - - --- Split a directory path into components. - -- Empty components are retained: the root directory becomes `{'', ''}`. - -- @function splitdir - -- @param path path - -- @return list of path components - -- @see catdir - -- @usage - -- dir_components = splitdir(filepath) - splitdir = X('splitdir(string)', function(path) - return split(path, dirsep) - end), - - - --- IO Functions - -- @section iofuncs - - --- Process files specified on the command-line. - -- Each filename is made the default input source with `io.input`, and - -- then the filename and argument number are passed to the callback - -- function. In list of filenames, `-` means `io.stdin`. If no - -- filenames were given, behave as if a single `-` was passed. - -- @todo Make the file list an argument to the function. - -- @function process_files - -- @tparam fileprocessor fn function called for each file argument - -- @usage - -- #! /usr/bin/env lua - -- -- minimal cat command - -- local io = require 'std.io' - -- io.process_files(function() io.write(io.slurp()) end) - process_files = X('process_files(function)', process_files), - - --- Read a file or file handle into a list of lines. - -- The lines in the returned list are not `\n` terminated. - -- @function readlines - -- @tparam[opt=io.input()] file|string file file handle or name; - -- if file is a file handle, that file is closed after reading - -- @treturn list lines - -- @usage - -- list = readlines '/etc/passwd' - readlines = X('readlines(?file|string)', readlines), - - --- Perform a shell command and return its output. - -- @function shell - -- @string c command - -- @treturn string output, or nil if error - -- @see os.execute - -- @usage - -- users = shell [[cat /etc/passwd | awk -F: '{print $1;}']] - shell = X('shell(string)', function(c) return slurp(popen(c)) end), - - --- Slurp a file handle. - -- @function slurp - -- @tparam[opt=io.input()] file|string file file handle or name; - -- if file is a file handle, that file is closed after reading - -- @return contents of file or handle, or nil if error - -- @see process_files - -- @usage - -- contents = slurp(filename) - slurp = X('slurp(?file|string)', slurp), - - --- Write values adding a newline after each. - -- @function writelines - -- @tparam[opt=io.output()] file h open writable file handle; - -- the file is **not** closed after writing - -- @tparam string|number ... values to write(as for write) - -- @usage - -- writelines(io.stdout, 'first line', 'next line') - writelines = X('writelines(?file|string|number, [string|number...])', writelines), -} - - -return merge(io, M) - - - ---- Types --- @section Types - ---- Signature of @{process_files} callback function. --- @function fileprocessor --- @string filename filename --- @int i argument number of *filename* --- @usage --- local fileprocessor = function(filename, i) --- io.write(tostring(i) .. ':\n===\n' .. io.slurp(filename) .. '\n') --- end --- io.process_files(fileprocessor) diff --git a/lib/std/math.lua b/lib/std/math.lua deleted file mode 100644 index d955862..0000000 --- a/lib/std/math.lua +++ /dev/null @@ -1,92 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core math module. - - The module table returned by `std.math` also contains all of the entries from - the core math table. An hygienic way to import this module, then, is simply - to override the core `math` locally: - - local math = require 'std.math' - - @corelibrary std.math -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck - -_ = nil - - -local _ENV = require 'std.normalize' { - 'math', - merge = 'table.merge', -} - - - ---[[ ================= ]]-- ---[[ Implementatation. ]]-- ---[[ ================= ]]-- - - -local M - - -local _floor = math.floor - -local function floor(n, p) - if(p or 0) == 0 then - return _floor(n) - end - local e = 10 ^ p - return _floor(n * e) / e -end - - -local function round(n, p) - local e = 10 ^(p or 0) - return _floor(n * e + 0.5) / e -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.math.' .. decl, fn) or fn -end - - -M = { - --- Core Functions - -- @section corefuncs - - --- Extend `math.floor` to take the number of decimal places. - -- @function floor - -- @number n number - -- @int[opt=0] p number of decimal places to truncate to - -- @treturn number `n` truncated to `p` decimal places - -- @usage - -- tenths = floor(magnitude, 1) - floor = X('floor(number, ?int)', floor), - - --- Round a number to a given number of decimal places. - -- @function round - -- @number n number - -- @int[opt=0] p number of decimal places to round to - -- @treturn number `n` rounded to `p` decimal places - -- @usage - -- roughly = round(exactly, 2) - round = X('round(number, ?int)', round), -} - - -return merge(math, M) diff --git a/lib/std/package.lua b/lib/std/package.lua deleted file mode 100644 index e3e8243..0000000 --- a/lib/std/package.lua +++ /dev/null @@ -1,263 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core package module. - - The module table returned by `std.package` also contains all of the entries - from the core `package` table. An hygienic way to import this module, then, is - simply to override core `package` locally: - - local package = require 'std.package' - - Manage `package.path` with normalization, duplicate removal, - insertion & removal of elements and automatic folding of '/' and '?' - onto `package.dirsep` and `package.pathmark`, for easy addition of - new paths. For example, instead of all this: - - lib = std.io.catfile('.', 'lib', package.pathmark .. '.lua') - paths = std.string.split(package.path, package.pathsep) - for i, path in ipairs(paths) do - -- ... lots of normalization code... - end - i = 1 - while i <= #paths do - if paths[i] == lib then - table.remove(paths, i) - else - i = i + 1 - end - end - table.insert(paths, 1, lib) - package.path = table.concat(paths, package.pathsep) - - You can now write just: - - package.path = package.normalize('./lib/?.lua', package.path) - - @corelibrary std.package -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck -local catfile = _.io.catfile -local escape_pattern = _.string.escape_pattern -local invert = _.table.invert -local split = _.string.split - -_ = nil - -local _ENV = require 'std.normalize' { - 'package', - concat = 'table.concat', - dirsep = 'package.dirsep', - gsub = 'string.gsub', - merge = 'table.merge', - pathmark = 'package.pathmark', - pathsep = 'package.pathsep', - string_find = 'string.find', - table_insert = 'table.insert', - table_remove = 'table.remove', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - ---- Make named constants for `package.config` --- (undocumented in 5.1; see luaconf.h for C equivalents). --- @table package --- @string dirsep directory separator --- @string pathsep path separator --- @string pathmark string that marks substitution points in a path template --- @string execdir(Windows only) replaced by the executable's directory in a path --- @string igmark Mark to ignore all before it when building `luaopen_` function name. - - -local function pathsub(path) - return gsub(path, '%%?.', function(capture) - if capture == '?' then - return pathmark - elseif capture == '/' then - return dirsep - else - return gsub(capture, '^%%', '', 1) - end - end) -end - - -local function find(pathstrings, patt, init, plain) - local paths = split(pathstrings, pathsep) - if plain then - patt = escape_pattern(patt) - end - init = init or 1 - if init < 0 then - init = #paths - init - end - for i = init, #paths do - if string_find(paths[i], patt) then - return i, paths[i] - end - end -end - - -local function normalize(...) - local i, paths, pathstrings = 1, {}, concat({...}, pathsep) - for _, path in ipairs(split(pathstrings, pathsep)) do - path = gsub(pathsub(path), catfile('^[^', ']'), catfile('.', '%0')) - path = gsub(path, catfile('', '%.', ''), dirsep) - path = gsub(path, catfile('', '%.$'), '') - path = gsub(path, catfile('^%.', '%..', ''), catfile('..', '')) - path = gsub(path, catfile('', '$'), '') - - -- Carefully remove redundant /foo/../ matches. - repeat - local again = false - path = gsub(path, catfile('', '([^', ']+)', '%.%.', ''), - function(dir1) - if dir1 == '..' then -- don't remove /../../ - return catfile('', '..', '..', '') - else - again = true - return dirsep - end - end) - path = gsub(path, catfile('', '([^', ']+)', '%.%.$'), - function(dir1) - if dir1 == '..' then -- don't remove /../.. - return catfile('', '..', '..') - else - again = true - return '' - end - end) - until again == false - - -- Build an inverted table of elements to eliminate duplicates after - -- normalization. - if not paths[path] then - paths[path], i = i, i + 1 - end - end - return concat(invert(paths), pathsep) -end - - -local function insert(pathstrings, ...) - local paths = split(pathstrings, pathsep) - table_insert(paths, ...) - return normalize(unpack(paths, 1, len(paths))) -end - - -local function mappath(pathstrings, callback, ...) - for _, path in ipairs(split(pathstrings, pathsep)) do - local r = callback(path, ...) - if r ~= nil then - return r - end - end -end - - -local function remove(pathstrings, pos) - local paths = split(pathstrings, pathsep) - table_remove(paths, pos) - return concat(paths, pathsep) -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.package.' .. decl, fn) or fn -end - - -local M = { - --- Look for a path segment match of *patt* in *pathstrings*. - -- @function find - -- @string pathstrings `pathsep` delimited path elements - -- @string patt a Lua pattern to search for in *pathstrings* - -- @int[opt=1] init element(not byte index!) to start search at. - -- Negative numbers begin counting backwards from the last element - -- @bool[opt=false] plain unless false, treat *patt* as a plain - -- string, not a pattern. Note that if *plain* is given, then *init* - -- must be given as well. - -- @return the matching element number(not byte index!) and full text - -- of the matching element, if any; otherwise nil - -- @usage - -- i, s = find(package.path, '^[^' .. package.dirsep .. '/]') - find = X('find(string, string, ?int, ?boolean|:plain)', find), - - --- Insert a new element into a `package.path` like string of paths. - -- @function insert - -- @string pathstrings a `package.path` like string - -- @int[opt=n+1] pos element index at which to insert *value*, where `n` is - -- the number of elements prior to insertion - -- @string value new path element to insert - -- @treturn string a new string with the new element inserted - -- @usage - -- package.path = insert(package.path, 1, install_dir .. '/?.lua') - insert = X('insert(string, [int], string)', insert), - - --- Call a function with each element of a path string. - -- @function mappath - -- @string pathstrings a `package.path` like string - -- @tparam mappathcb callback function to call for each element - -- @param ... additional arguments passed to *callback* - -- @return nil, or first non-nil returned by *callback* - -- @usage - -- mappath(package.path, searcherfn, transformfn) - mappath = X('mappath(string, function, [any...])', mappath), - - --- Normalize a path list. - -- Removing redundant `.` and `..` directories, and keep only the first - -- instance of duplicate elements. Each argument can contain any number - -- of `pathsep` delimited elements; wherein characters are subject to - -- `/` and `?` normalization, converting `/` to `dirsep` and `?` to - -- `pathmark`(unless immediately preceded by a `%` character). - -- @function normalize - -- @param ... path elements - -- @treturn string a single normalized `pathsep` delimited paths string - -- @usage - -- package.path = normalize(user_paths, sys_paths, package.path) - normalize = X('normalize(string...)', normalize), - - --- Remove any element from a `package.path` like string of paths. - -- @function remove - -- @string pathstrings a `package.path` like string - -- @int[opt=n] pos element index from which to remove an item, where `n` - -- is the number of elements prior to removal - -- @treturn string a new string with given element removed - -- @usage - -- package.path = remove(package.path) - remove = X('remove(string, ?int)', remove), -} - - -return merge(package, M) - - ---- Types --- @section Types - ---- Function signature of a callback for @{mappath}. --- @function mappathcb --- @string element an element from a `pathsep` delimited string of --- paths --- @param ... additional arguments propagated from @{mappath} --- @return non-nil to break, otherwise continue with the next element diff --git a/lib/std/string.lua b/lib/std/string.lua deleted file mode 100644 index 6ad9014..0000000 --- a/lib/std/string.lua +++ /dev/null @@ -1,505 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Additions to the core string module. - - The module table returned by `std.string` also contains all of the entries - from the core string table. An hygienic way to import this module, then, is - simply to override the core `string` locally: - - local string = require 'std.string' - - @corelibrary std.string -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.std.typecheck.argscheck -local escape_pattern = _.string.escape_pattern -local split = _.string.split - -_ = nil - - -local _ENV = require 'std.normalize' { - 'string', - abs = 'math.abs', - concat = 'table.concat', - find = 'string.find', - floor = 'math.floor', - format = 'string.format', - gsub = 'string.gsub', - insert = 'table.insert', - match = 'string.match', - merge = 'table.merge', - render = 'string.render', - sort = 'table.sort', - sub = 'string.sub', - upper = 'string.upper', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local M - - -local function toqstring(x, xstr) - if type(x) ~= 'string' then - return xstr - end - return format('%q', x) -end - - -local concatvfns = { - elem = tostring, - term = function(x) - return type(x) ~= 'table' or getmetamethod(x, '__tostring') - end, - sort = function(keys) - return keys - end, - open = function(x) return '{' end, - close = function(x) return '}' end, - pair = function(x, kp, vp, k, v, kstr, vstr, seqp) - return toqstring(k, kstr) .. '=' .. toqstring(v, vstr) - end, - sep = function(x, kp, vp, kn, vn, seqp) - return kp ~= nil and kn ~= nil and ',' or '' - end, -} - - -local function __concat(s, o) - -- Don't use normalize.str here, because we don't want ASCII escape rendering. - return render(s, concatvfns) .. render(o, concatvfns) -end - - -local function __index(s, i) - if type(i) == 'number' then - return sub(s, i, i) - else - -- Fall back to module metamethods - return M[i] - end -end - - -local _format = string.format - -local function format(f, arg1, ...) - return(arg1 ~= nil) and _format(f, arg1, ...) or f -end - - -local function tpack(from, to, ...) - return from, to, {...} -end - -local function tfind(s, ...) - return tpack(find(s, ...)) -end - - -local function finds(s, p, i, ...) - i = i or 1 - local l = {} - local from, to, r - repeat - from, to, r = tfind(s, p, i, ...) - if from ~= nil then - insert(l, {from, to, capt=r}) - i = to + 1 - end - until not from - return l -end - - -local function caps(s) - return(gsub(s, '(%w)([%w]*)', function(l, ls) - return upper(l) .. ls - end)) -end - - -local function escape_shell(s) - return(gsub(s, '([ %(%)%\\%[%]\'"])', '\\%1')) -end - - -local function ordinal_suffix(n) - n = abs(n) % 100 - local d = n % 10 - if d == 1 and n ~= 11 then - return 'st' - elseif d == 2 and n ~= 12 then - return 'nd' - elseif d == 3 and n ~= 13 then - return 'rd' - else - return 'th' - end -end - - -local function pad(s, w, p) - p = string.rep(p or ' ', abs(w)) - if w < 0 then - return string.sub(p .. s, w) - end - return string.sub(s .. p, 1, w) -end - - -local function wrap(s, w, ind, ind1) - w = w or 78 - ind = ind or 0 - ind1 = ind1 or ind - assert(ind1 < w and ind < w, - 'the indents must be less than the line width') - local r = {string.rep(' ', ind1)} - local i, lstart, lens = 1, ind1, len(s) - while i <= lens do - local j = i + w - lstart - while len(s[j]) > 0 and s[j] ~= ' ' and j > i do - j = j - 1 - end - local ni = j + 1 - while s[j] == ' ' do - j = j - 1 - end - insert(r, sub(s, i, j)) - i = ni - if i < lens then - insert(r, '\n' .. string.rep(' ', ind)) - lstart = ind - end - end - return concat(r) -end - - -local function numbertosi(n) - local SIprefix = { - [-8]='y', [-7]='z', [-6]='a', [-5]='f', - [-4]='p', [-3]='n', [-2]='mu', [-1]='m', - [0]='', [1]='k', [2]='M', [3]='G', - [4]='T', [5]='P', [6]='E', [7]='Z', - [8]='Y' - } - local t = _format('% #.2e', n) - local _, _, m, e = find(t, '.(.%...)e(.+)') - local man, exp = tonumber(m), tonumber(e) - local siexp = floor(exp / 3) - local shift = exp - siexp * 3 - local s = SIprefix[siexp] or 'e' .. tostring(siexp) - man = man *(10 ^ shift) - return _format('%0.f', man) .. s -end - - --- Ordor numbers first then asciibetically. -local function keycmp(a, b) - if type(a) == 'number' then - return type(b) ~= 'number' or a < b - end - return type(b) ~= 'number' and tostring(a) < tostring(b) -end - - -local render_fallbacks = { - __index = concatvfns, -} - - -local function prettytostring(x, indent, spacing) - indent = indent or '\t' - spacing = spacing or '' - return render(x, setmetatable({ - elem = function(x) - if type(x) ~= 'string' then - return tostring(x) - end - return format('%q', x) - end, - - sort = function(keylist) - sort(keylist, keycmp) - return keylist - end, - - open = function() - local s = spacing .. '{' - spacing = spacing .. indent - return s - end, - - close = function() - spacing = string.gsub(spacing, indent .. '$', '') - return spacing .. '}' - end, - - pair = function(x, _, _, k, v, kstr, vstr) - local type_k = type(k) - local s = spacing - if type_k ~= 'string' or match(k, '[^%w_]') then - s = s .. '[' - if type_k == 'table' then - s = s .. '\n' - end - s = s .. kstr - if type_k == 'table' then - s = s .. '\n' - end - s = s .. ']' - else - s = s .. k - end - s = s .. ' =' - if type(v) == 'table' then - s = s .. '\n' - else - s = s .. ' ' - end - s = s .. vstr - return s - end, - - sep = function(_, k) - local s = '\n' - if k then - s = ',' .. s - end - return s - end, - }, render_fallbacks)) -end - - -local function trim(s, r) - r = r or '%s+' - return (gsub(gsub(s, '^' .. r, ''), r .. '$', '')) -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.string.' .. decl, fn) or fn -end - -M = { - --- Metamethods - -- @section metamethods - - --- String concatenation operation. - -- @function __concat - -- @string s initial string - -- @param o object to stringify and concatenate - -- @return s .. tostring(o) - -- @usage - -- local string = setmetatable('', require 'std.string') - -- concatenated = 'foo' .. {'bar'} - __concat = __concat, - - --- String subscript operation. - -- @function __index - -- @string s string - -- @tparam int|string i index or method name - -- @return `sub(s, i, i)` if i is a number, otherwise - -- fall back to a `std.string` metamethod(if any). - -- @usage - -- getmetatable('').__index = require 'std.string'.__index - -- third =('12345')[3] - __index = __index, - - - --- Core Functions - -- @section corefuncs - - --- Capitalise each word in a string. - -- @function caps - -- @string s any string - -- @treturn string *s* with each word capitalized - -- @usage - -- userfullname = caps(input_string) - caps = X('caps(string)', caps), - - --- Remove any final newline from a string. - -- @function chomp - -- @string s any string - -- @treturn string *s* with any single trailing newline removed - -- @usage - -- line = chomp(line) - chomp = X('chomp(string)', function(s) - return(gsub(s, '\n$', '')) - end), - - --- Escape a string to be used as a pattern. - -- @function escape_pattern - -- @string s any string - -- @treturn string *s* with active pattern characters escaped - -- @usage - -- substr = match(inputstr, escape_pattern(literal)) - escape_pattern = X('escape_pattern(string)', escape_pattern), - - --- Escape a string to be used as a shell token. - -- Quotes spaces, parentheses, brackets, quotes, apostrophes and - -- whitespace. - -- @function escape_shell - -- @string s any string - -- @treturn string *s* with active shell characters escaped - -- @usage - -- os.execute('echo ' .. escape_shell(outputstr)) - escape_shell = X('escape_shell(string)', escape_shell), - - --- Repeatedly `string.find` until target string is exhausted. - -- @function finds - -- @string s target string - -- @string pattern pattern to match in *s* - -- @int[opt=1] init start position - -- @bool[opt] plain inhibit magic characters - -- @return list of `{from, to; capt={captures}}` - -- @see std.string.tfind - -- @usage - -- for t in std.elems(finds('the target string', '%S+')) do - -- print(tostring(t.capt)) - -- end - finds = X('finds(string, string, ?int, ?boolean|:plain)', finds), - - --- Extend to work better with one argument. - -- If only one argument is passed, no formatting is attempted. - -- @function format - -- @string f format string - -- @param[opt] ... arguments to format - -- @return formatted string - -- @usage - -- print(format '100% stdlib!') - format = X('format(string, [any...])', format), - - --- Remove leading matter from a string. - -- @function ltrim - -- @string s any string - -- @string[opt='%s+'] r leading pattern - -- @treturn string *s* with leading *r* stripped - -- @usage - -- print('got: ' .. ltrim(userinput)) - ltrim = X('ltrim(string, ?string)', function(s, r) - return (gsub(s, '^' ..(r or '%s+'), '')) - end), - - --- Write a number using SI suffixes. - -- The number is always written to 3 s.f. - -- @function numbertosi - -- @tparam number|string n any numeric value - -- @treturn string *n* simplifed using largest available SI suffix. - -- @usage - -- print(numbertosi(bitspersecond) .. 'bps') - numbertosi = X('numbertosi(number|string)', numbertosi), - - --- Return the English suffix for an ordinal. - -- @function ordinal_suffix - -- @tparam int|string n any integer value - -- @treturn string English suffix for *n* - -- @usage - -- local now = os.date '*t' - -- print('%d%s day of the week', now.day, ordinal_suffix(now.day)) - ordinal_suffix = X('ordinal_suffix(int|string)', ordinal_suffix), - - --- Justify a string. - -- When the string is longer than w, it is truncated(left or right - -- according to the sign of w). - -- @function pad - -- @string s a string to justify - -- @int w width to justify to(-ve means right-justify; +ve means - -- left-justify) - -- @string[opt=' '] p string to pad with - -- @treturn string *s* justified to *w* characters wide - -- @usage - -- print(pad(trim(outputstr, 78)) .. '\n') - pad = X('pad(string, int, ?string)', pad), - - --- Pretty-print a table, or other object. - -- @function prettytostring - -- @param x object to convert to string - -- @string[opt='\t'] indent indent between levels - -- @string[opt=''] spacing space before every line - -- @treturn string pretty string rendering of *x* - -- @usage - -- print(prettytostring(std, ' ')) - prettytostring = X('prettytostring(?any, ?string, ?string)', prettytostring), - - --- Remove trailing matter from a string. - -- @function rtrim - -- @string s any string - -- @string[opt='%s+'] r trailing pattern - -- @treturn string *s* with trailing *r* stripped - -- @usage - -- print('got: ' .. rtrim(userinput)) - rtrim = X('rtrim(string, ?string)', function(s, r) - return (gsub(s, (r or '%s+') .. '$', '')) - end), - - --- Split a string at a given separator. - -- Separator is a Lua pattern, so you have to escape active characters, - -- `^$()%.[]*+-?` with a `%` prefix to match a literal character in *s*. - -- @function split - -- @string s to split - -- @string[opt='%s+'] sep separator pattern - -- @return list of strings - -- @usage - -- words = split 'a very short sentence' - split = X('split(string, ?string)', split), - - --- Do `string.find`, returning a table of captures. - -- @function tfind - -- @string s target string - -- @string pattern pattern to match in *s* - -- @int[opt=1] init start position - -- @bool[opt] plain inhibit magic characters - -- @treturn int start of match - -- @treturn int end of match - -- @treturn table list of captured strings - -- @see std.string.finds - -- @usage - -- b, e, captures = tfind('the target string', '%s', 10) - tfind = X('tfind(string, string, ?int, ?boolean|:plain)', tfind), - - --- Remove leading and trailing matter from a string. - -- @function trim - -- @string s any string - -- @string[opt='%s+'] r trailing pattern - -- @treturn string *s* with leading and trailing *r* stripped - -- @usage - -- print('got: ' .. trim(userinput)) - trim = X('trim(string, ?string)', trim), - - --- Wrap a string into a paragraph. - -- @function wrap - -- @string s a paragraph of text - -- @int[opt=78] w width to wrap to - -- @int[opt=0] ind indent - -- @int[opt=ind] ind1 indent of first line - -- @treturn string *s* wrapped to *w* columns - -- @usage - -- print(wrap(copyright, 72, 4)) - wrap = X('wrap(string, ?int, ?int, ?int)', wrap), -} - - -return merge(string, M) - diff --git a/lib/std/table.lua b/lib/std/table.lua deleted file mode 100644 index 7bda608..0000000 --- a/lib/std/table.lua +++ /dev/null @@ -1,439 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2002-2018 stdlib authors -]] ---[[-- - Extensions to the core table module. - - The module table returned by `std.table` also contains all of the entries from - the core table module. An hygienic way to import this module, then, is simply - to override the core `table` locally: - - local table = require 'std.table' - - @corelibrary std.table -]] - - -local _ = require 'std._base' - -local argscheck = _.typecheck and _.typecheck.argscheck -local invert = _.table.invert -local maxn = _.table.maxn - -_ = nil - -local _ENV = require 'std.normalize' { - 'table', - merge = 'table.merge', - min = 'math.min', -} - - - ---[[ =============== ]]-- ---[[ Implementation. ]]-- ---[[ =============== ]]-- - - -local M - - -local function merge_allfields(t, u, map, nometa) - if type(map) ~= 'table' then - map, nometa = nil, map - end - - if not nometa then - setmetatable(t, getmetatable(u)) - end - if map then - for k, v in pairs(u) do - t[map[k] or k] = v - end - else - for k, v in pairs(u) do - t[k] = v - end - end - return t -end - - -local function merge_namedfields(t, u, keys, nometa) - if type(keys) ~= 'table' then - keys, nometa = nil, keys - end - - if not nometa then - setmetatable(t, getmetatable(u)) - end - for _, k in pairs(keys or {}) do - t[k] = u[k] - end - return t -end - - -local function depair(ls) - local t = {} - for _, v in ipairs(ls) do - t[v[1]] = v[2] - end - return t -end - - -local function enpair(t) - local tt = {} - for i, v in pairs(t) do - tt[#tt + 1] = {i, v} - end - return tt -end - - -local _insert = table.insert - -local function insert(t, pos, v) - if v == nil then - pos, v = len(t) + 1, pos - end - if pos < 1 or pos > len(t) + 1 then - argerror('std.table.insert', 2, 'position ' .. pos .. ' out of bounds', 2) - end - _insert(t, pos, v) - return t -end - - -local function keys(t) - local l = {} - for k in pairs(t) do - l[#l + 1] = k - end - return l -end - - -local function new(x, t) - return setmetatable(t or {}, {__index = function(t, i) - return x - end}) -end - - -local function project(fkey, tt) - local r = {} - for _, t in ipairs(tt) do - r[#r + 1] = t[fkey] - end - return r -end - - -local function size(t) - local n = 0 - for _ in pairs(t) do - n = n + 1 - end - return n -end - - --- Preserve core table sort function. -local _sort = table.sort - -local function sort(t, c) - _sort(t, c) - return t -end - - -local _remove = table.remove - -local function remove(t, pos) - local lent = len(t) - pos = pos or lent - if pos < min(1, lent) or pos > lent + 1 then -- +1? whu? that's what 5.2.3 does!?! - argerror('std.table.remove', 2, 'position ' .. pos .. ' out of bounds', 2) - end - return _remove(t, pos) -end - - -local _unpack = unpack - -local function unpack(t, i, j) - if j == nil then - -- if j was not given, respect __len, otherwise use maxn - local m = getmetamethod(t, '__len') - j = m and m(t) or maxn(t) - end - return _unpack(t, tonumber(i) or 1, tonumber(j)) -end - - -local function values(t) - local l = {} - for _, v in pairs(t) do - l[#l + 1] = v - end - return l -end - - - ---[[ ================= ]]-- ---[[ Public Interface. ]]-- ---[[ ================= ]]-- - - -local function X(decl, fn) - return argscheck and argscheck('std.table.' .. decl, fn) or fn -end - -M = { - --- Core Functions - -- @section corefuncs - - --- Enhance core *table.insert* to return its result. - -- If *pos* is not given, respect `__len` metamethod when calculating - -- default append. Also, diagnose out of bounds *pos* arguments - -- consistently on any supported version of Lua. - -- @function insert - -- @tparam table t a table - -- @int[opt=len(t)] pos index at which to insert new element - -- @param v value to insert into *t* - -- @treturn table *t* - -- @usage - -- --> {1, 'x', 2, 3, 'y'} - -- insert(insert({1, 2, 3}, 2, 'x'), 'y') - insert = X('insert(table, [int], any)', insert), - - --- Largest integer key in a table. - -- @function maxn - -- @tparam table t a table - -- @treturn int largest integer key in *t* - -- @usage - -- --> 42 - -- maxn {'a', b='c', 99, [42]='x', 'x', [5]=67} - maxn = X('maxn(table)', maxn), - - --- Turn a tuple into a list, with tuple-size in field `n` - -- @function pack - -- @param ... tuple - -- @return list-like table, with tuple-size in field `n` - -- @usage - -- --> {1, 2, 'ax', n=3} - -- pack(find('ax1', '(%D+)')) - pack = pack, - - --- Enhance core *table.remove* to respect `__len` when *pos* is omitted. - -- Also, diagnose out of bounds *pos* arguments consistently on any supported - -- version of Lua. - -- @function remove - -- @tparam table t a table - -- @int[opt=len(t)] pos index from which to remove an element - -- @return removed value, or else `nil` - -- @usage - -- --> {1, 2, 5} - -- t = {1, 2, 'x', 5} - -- remove(t, 3) == 'x' and t - remove = X('remove(table, ?int)', remove), - - --- Enhance core *table.sort* to return its result. - -- @function sort - -- @tparam table t unsorted table - -- @tparam[opt=std.operator.lt] comparator c ordering function callback - -- @return *t* with keys sorted according to *c* - -- @usage - -- table.concat(sort(object)) - sort = X('sort(table, ?function)', sort), - - --- Enhance core *table.unpack* to always unpack up to __len or maxn. - -- @function unpack - -- @tparam table t table to act on - -- @int[opt=1] i first index to unpack - -- @int[opt=table.maxn(t)] j last index to unpack - -- @return ... values of numeric indices of *t* - -- @usage - -- return unpack(results_table) - unpack = X('unpack(table, ?int, ?int)', unpack), - - - --- Accessor Functions - -- @section accessorfuncs - - --- Make a shallow copy of a table, including any metatable. - -- @function clone - -- @tparam table t source table - -- @tparam[opt={}] table map table of `{old_key=new_key, ...}` - -- @bool[opt] nometa if non-nil don't copy metatable - -- @return copy of *t*, also sharing *t*'s metatable unless *nometa* - -- is true, and with keys renamed according to *map* - -- @see merge - -- @see clone_select - -- @usage - -- shallowcopy = clone(original, {rename_this='to_this'}, ':nometa') - clone = X('clone(table, [table], ?boolean|:nometa)', function(...) - return merge_allfields({}, ...) - end), - - --- Make a partial clone of a table. - -- - -- Like `clone`, but does not copy any fields by default. - -- @function clone_select - -- @tparam table t source table - -- @tparam[opt={}] table keys list of keys to copy - -- @bool[opt] nometa if non-nil don't copy metatable - -- @treturn table copy of fields in *selection* from *t*, also sharing *t*'s - -- metatable unless *nometa* - -- @see clone - -- @see merge_select - -- @usage - -- partialcopy = clone_select(original, {'this', 'and_this'}, true) - clone_select = X('clone_select(table, [table], ?boolean|:nometa)', function(...) - return merge_namedfields({}, ...) - end), - - --- Turn a list of pairs into a table. - -- @todo Find a better name. - -- @function depair - -- @tparam table ls list of lists - -- @treturn table a flat table with keys and values from *ls* - -- @see enpair - -- @usage - -- --> {a=1, b=2, c=3} - -- depair {{'a', 1}, {'b', 2}, {'c', 3}} - depair = X('depair(list of lists)', depair), - - --- Turn a table into a list of pairs. - -- @todo Find a better name. - -- @function enpair - -- @tparam table t a table `{i1=v1, ..., in=vn}` - -- @treturn table a new list of pairs containing `{{i1, v1}, ..., {in, vn}}` - -- @see depair - -- @usage - -- --> {{1, 'a'}, {2, 'b'}, {3, 'c'}} - -- enpair {'a', 'b', 'c'} - enpair = X('enpair(table)', enpair), - - --- Return whether table is empty. - -- @function empty - -- @tparam table t any table - -- @treturn boolean `true` if *t* is empty, otherwise `false` - -- @usage - -- if empty(t) then error 'ohnoes' end - empty = X('empty(table)', function(t) - return not next(t) - end), - - --- Make a table with a default value for unset keys. - -- @function new - -- @param[opt=nil] x default entry value - -- @tparam[opt={}] table t initial table - -- @treturn table table whose unset elements are *x* - -- @usage - -- t = new(0) - new = X('new(?any, ?table)', new), - - --- Project a list of fields from a list of tables. - -- @function project - -- @param fkey field to project - -- @tparam table tt a list of tables - -- @treturn table list of *fkey* fields from *tt* - -- @usage - -- --> {1, 3, 'yy'} - -- project('xx', {{'a', xx=1, yy='z'}, {'b', yy=2}, {'c', xx=3}, {xx='yy'}) - project = X('project(any, list of tables)', project), - - --- Find the number of elements in a table. - -- @function size - -- @tparam table t any table - -- @treturn int number of non-nil values in *t* - -- @usage - -- --> 3 - -- size {foo=true, bar=true, baz=false} - size = X('size(table)', size), - - --- Make the list of values of a table. - -- @function values - -- @tparam table t any table - -- @treturn table list of values in *t* - -- @see keys - -- @usage - -- --> {'a', 'c', 42} - -- values {'a', b='c', [-1]=42} - values = X('values(table)', values), - - - --- Mutator Functions - -- @section mutatorfuncs - - --- Invert a table. - -- @function invert - -- @tparam table t a table with `{k=v, ...}` - -- @treturn table inverted table `{v=k, ...}` - -- @usage - -- --> {a=1, b=2, c=3} - -- invert {'a', 'b', 'c'} - invert = X('invert(table)', invert), - - --- Make the list of keys in table. - -- @function keys - -- @tparam table t a table - -- @treturn table list of keys from *t* - -- @see values - -- @usage - -- globals = keys(_G) - keys = X('keys(table)', keys), - - --- Destructively merge one table's fields into another. - -- @function merge - -- @tparam table t destination table - -- @tparam table u table with fields to merge - -- @tparam[opt={}] table map table of `{old_key=new_key, ...}` - -- @bool[opt] nometa if `true` or ':nometa' don't copy metatable - -- @treturn table *t* with fields from *u* merged in - -- @see clone - -- @see merge_select - -- @usage - -- merge(_G, require 'std.debug', {say='log'}, ':nometa') - merge = X('merge(table, table, [table], ?boolean|:nometa)', merge_allfields), - - --- Destructively merge another table's named fields into *table*. - -- - -- Like `merge`, but does not merge any fields by default. - -- @function merge_select - -- @tparam table t destination table - -- @tparam table u table with fields to merge - -- @tparam[opt={}] table keys list of keys to copy - -- @bool[opt] nometa if `true` or ':nometa' don't copy metatable - -- @treturn table copy of fields in *selection* from *t*, also sharing *t*'s - -- metatable unless *nometa* - -- @see merge - -- @see clone_select - -- @usage - -- merge_select(_G, require 'std.debug', {'say'}, false) - merge_select = X('merge_select(table, table, [table], ?boolean|:nometa)', - merge_namedfields), -} - - -return merge(table, M) - - - ---- Types --- @section Types - ---- Signature of a @{sort} comparator function. --- @function comparator --- @param a any object --- @param b any object --- @treturn boolean `true` if *a* sorts before *b*, otherwise `false` --- @see sort --- @usage --- local reversor = function(a, b) return a > b end --- sort(t, reversor) diff --git a/modules/std.debug.html b/modules/std.debug.html new file mode 100644 index 0000000..052f34c --- /dev/null +++ b/modules/std.debug.html @@ -0,0 +1,857 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.debug

+

Additions to the core debug module.

+

The module table returned by std.debug also contains all of the entries + from the core debug table. An hygienic way to import this module, then, is + simply to override the core debug locally:

+ + +
+local debug = require "std.debug"
+
+ +

The behaviour of the functions in this module are controlled by the value + of the global _DEBUG. Not setting _DEBUG prior to requiring any of + stdlib's modules is equivalent to having _DEBUG = true.

+ +

The first line of Lua code in production quality projects that use stdlib + should be either:

+ + +
+_DEBUG = false
+
+ +

or alternatively, if you need to be careful not to damage the global + environment:

+ + +
+local init = require "std.debug_init"
+init._DEBUG = false
+
+ +

This mitigates almost all of the overhead of argument typechecking in + stdlib API functions.

+ + +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DEPRECATED (version, name[, extramsg], fn)Provide a deprecated function definition according to _DEBUG.deprecate.
DEPRECATIONMSG (version, name[, extramsg], level)Format a deprecation warning message.
argcheck (name, i, expected, actual[, level=2])Check the type of an argument against expected types.
argerror (name, i[, extramsg[, level=1]])Raise a bad argument error.
argscheck (decl, inner)Wrap a function definition with argument type and arity checking.
debug ()Equivalent to calling debug.say (1, ...)
extramsg_mismatch (expected, actual[, index])Format a type mismatch error.
parsetypes (types)Compact permutation list into a list of valid types at each argument.
say ([n=1], ...)Print a debugging message to io.stderr.
trace (event)Trace function calls.
+

Tables

+ + + + + +
_DEBUGControl std.debug function behaviour.
+

Fields

+ + + + + + + + + + + + + + + + + + + + + +
extramsg_toomanyFormat a too many things error.
getfenvExtend debug.getfenv to unwrap functables correctly.
resulterrorRaise a bad result error.
setfenvExtend debug.setfenv to unwrap functables correctly.
typesplitSplit a typespec string into a table of normalized type names.
+ +
+
+ + +

Functions

+ Methods +
+
+ + DEPRECATED (version, name[, extramsg], fn) +
+
+ Provide a deprecated function definition according to _DEBUG.deprecate. + You can check whether your covered code uses deprecated functions by + setting _DEBUG.deprecate to true before loading any stdlib modules, + or silence deprecation warnings by setting _DEBUG.deprecate = false. + + +

Parameters:

+
    +
  • version + string + first deprecation release version +
  • +
  • name + string + function name for automatic warning message +
  • +
  • extramsg + string + additional warning text + (optional) +
  • +
  • fn + func + deprecated function +
  • +
+ +

Returns:

+
    + + a function to show the warning on first call, and hand off to fn +
+ + + +

Usage:

+
    +
    M.op = DEPRECATED ("41", "'std.functional.op'", std.operator)
    +
+ +
+
+ + DEPRECATIONMSG (version, name[, extramsg], level) +
+
+ Format a deprecation warning message. + + +

Parameters:

+
    +
  • version + string + first deprecation release version +
  • +
  • name + string + function name for automatic warning message +
  • +
  • extramsg + string + additional warning text + (optional) +
  • +
  • level + int + call stack level to blame for the error +
  • +
+ +

Returns:

+
    + + string + deprecation warning message, or empty string +
+ + + +

Usage:

+
    +
    io.stderr:write (DEPRECATIONMSG ("42", "multi-argument 'module.fname'", 2))
    +
+ +
+
+ + argcheck (name, i, expected, actual[, level=2]) +
+
+ Check the type of an argument against expected types. + Equivalent to luaL_argcheck in the Lua C API.

+ +

Call argerror if there is a type mismatch.

+ +

Argument actual must match one of the types from in expected, each + of which can be the name of a primitive Lua type, a stdlib object type, + or one of the special options below:

+ +
#table    accept any non-empty table
+any       accept any non-nil argument type
+file      accept an open file object
+function  accept a function, or object with a __call metamethod
+int       accept an integer valued number
+list      accept a table where all keys are a contiguous 1-based integer range
+#list     accept any non-empty list
+object    accept any std.Object derived type
+:foo      accept only the exact string ":foo", works for any :-prefixed string
+
+ +

The :foo format allows for type-checking of self-documenting + boolean-like constant string parameters predicated on nil versus + :option instead of false versus true. Or you could support + both:

+ +
argcheck ("table.copy", 2, "boolean|:nometa|nil", nometa)
+
+ +

A very common pattern is to have a list of possible types including + "nil" when the argument is optional. Rather than writing long-hand + as above, prepend a question mark to the list of types and omit the + explicit "nil" entry:

+ +
argcheck ("table.copy", 2, "?boolean|:nometa", predicate)
+
+ +

Normally, you should not need to use the level parameter, as the + default is to blame the caller of the function using argcheck in + error messages; which is almost certainly what you want. + + +

Parameters:

+
    +
  • name + string + function to blame in error message +
  • +
  • i + int + argument number to blame in error message +
  • +
  • expected + string + specification for acceptable argument types +
  • +
  • actual + argument passed +
  • +
  • level + int + call stack level to blame for the error + (default 2) +
  • +
+ + + + +

Usage:

+
    +
    + local function case (with, branches)
    +   argcheck ("std.functional.case", 2, "#table", branches)
    +   ...
    +
+ +
+
+ + argerror (name, i[, extramsg[, level=1]]) +
+
+ Raise a bad argument error. + Equivalent to luaL_argerror in the Lua C API. This function does not + return. The level argument behaves just like the core error + function. + + +

Parameters:

+
    +
  • name + string + function to callout in error message +
  • +
  • i + int + argument number +
  • +
  • extramsg + string + additional text to append to message inside parentheses + (optional) +
  • +
  • level + int + call stack level to blame for the error + (default 1) +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    + local function slurp (file)
    +   local h, err = input_handle (file)
    +   if h == nil then argerror ("std.io.slurp", 1, err, 2) end
    +   ...
    +
+ +
+
+ + argscheck (decl, inner) +
+
+ +

Wrap a function definition with argument type and arity checking. + In addition to checking that each argument type matches the corresponding + element in the types table with argcheck, if the final element of + types ends with an ellipsis, remaining unchecked arguments are checked + against that type:

+ +
 format = argscheck ("string.format (string, ?any...)", string.format)
+
+ +

A colon in the function name indicates that the argument type list does + not have a type for self:

+ +
 format = argscheck ("string:format (?any...)", string.format)
+
+ +

If an argument can be omitted entirely, then put its type specification + in square brackets:

+ +
 insert = argscheck ("table.insert (table, [int], ?any)", table.insert)
+
+ +

Similarly return types can be checked with the same list syntax as + arguments:

+ +
 len = argscheck ("string.len (string) => int", string.len)
+
+ +

Additionally, variant return type lists can be listed like this:

+ +
 open = argscheck ("io.open (string, ?string) => file or nil, string",
+                   io.open)
+
+ + + + +

Parameters:

+
    +
  • decl + string + function type declaration string +
  • +
  • inner + func + function to wrap with argument checking +
  • +
+ + + + +

Usage:

+
    +
    + local case = argscheck ("std.functional.case (?any, #table) => [any...]",
    +   function (with, branches)
    +     ...
    + end)
    +
+ +
+
+ + debug () +
+
+ Equivalent to calling debug.say (1, ...) + + + + + +

See also:

+ + +

Usage:

+
    +
    + local debug = require "std.debug"
    + debug "oh noes!"
    +
+ +
+
+ + extramsg_mismatch (expected, actual[, index]) +
+
+ Format a type mismatch error. + + +

Parameters:

+
    +
  • expected + string + a pipe delimited list of matchable types +
  • +
  • actual + the actual argument to match with +
  • +
  • index + number + erroring container element index + (optional) +
  • +
+ +

Returns:

+
    + + string + formatted extramsg for this mismatch for argerror +
+ + +

See also:

+ + +

Usage:

+
    +
    +   if fmt ~= nil and type (fmt) ~= "string" then
    +     argerror ("format", 1, extramsg_mismatch ("?string", fmt))
    +   end
    +
+ +
+
+ + parsetypes (types) +
+
+ Compact permutation list into a list of valid types at each argument. + Eliminate bracketed types by combining all valid types at each position + for all permutations of typelist. + + +

Parameters:

+
    +
  • types + list + a normalized list of type names +
  • +
+ +

Returns:

+
    + + list + valid types for each positional parameter +
+ + + + +
+
+ + say ([n=1], ...) +
+
+ Print a debugging message to io.stderr. + Display arguments passed through std.tostring and separated by tab + characters when _DEBUG is true and n is 1 or less; or _DEBUG.level + is a number greater than or equal to n. If _DEBUG is false or + nil, nothing is written. + + +

Parameters:

+
    +
  • n + int + debugging level, smaller is higher priority + (default 1) +
  • +
  • ... + objects to print (as for print) +
  • +
+ + + + +

Usage:

+
    +
    + local _DEBUG = require "std.debug_init"._DEBUG
    + _DEBUG.level = 3
    + say (2, "_DEBUG table contents:", _DEBUG)
    +
+ +
+
+ + trace (event) +
+
+ Trace function calls. + Use as debug.sethook (trace, "cr"), which is done automatically + when _DEBUG.call is set. + Based on test/trace-calls.lua from the Lua distribution. + + +

Parameters:

+
    +
  • event + string + event causing the call +
  • +
+ + + + +

Usage:

+
    +
    + _DEBUG = { call = true }
    + local debug = require "std.debug"
    +
+ +
+
+

Tables

+ +
+
+ + _DEBUG +
+
+ Control std.debug function behaviour. + To declare debugging state, set _DEBUG either to false to disable all + runtime debugging; to any "truthy" value (equivalent to enabling everything + except call, or as documented below. + + +

Fields:

+
    +
  • argcheck + boolean + honor argcheck and argscheck calls + (default true) +
  • +
  • call + boolean + do call trace debugging + (default false) +
  • +
  • deprecate + if false, deprecated APIs are defined, + and do not issue deprecation warnings when used; if nil issue a + deprecation warning each time a deprecated api is used; any other + value causes deprecated APIs not to be defined at all + (default nil) +
  • +
  • level + int + debugging level + (default 1) +
  • +
+ + + + +

Usage:

+
    +
    _DEBUG = { argcheck = false, level = 9 }
    +
+ +
+
+

Fields

+ +
+
+ + extramsg_toomany +
+
+ Format a too many things error. + + +
    +
  • bad + string + the thing there are too many of +
  • +
  • expected + int + maximum number of bad things expected +
  • +
  • actual + int + actual number of bad things that triggered the error +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    +   if maxn (argt) > 7 then
    +     argerror ("sevenses", 8, extramsg_toomany ("argument", 7, maxn (argt)))
    +   end
    +
+ +
+
+ + getfenv +
+
+ Extend debug.getfenv to unwrap functables correctly. + + +
    +
  • fn + int, function or functable + target function, or stack level +
  • +
+ + + + + +
+
+ + resulterror +
+
+ Raise a bad result error. + Like argerror for bad results. This function does not + return. The level argument behaves just like the core error + function. + + +
    +
  • name + string + function to callout in error message +
  • +
  • i + int + argument number +
  • +
  • extramsg + string + additional text to append to message inside parentheses + (optional) +
  • +
  • level + int + call stack level to blame for the error + (default 1) +
  • +
+ + + + +

Usage:

+
    +
    + local function slurp (file)
    +   local h, err = input_handle (file)
    +   if h == nil then argerror ("std.io.slurp", 1, err, 2) end
    +   ...
    +
+ +
+
+ + setfenv +
+
+ Extend debug.setfenv to unwrap functables correctly. + + +
    +
  • fn + function or functable + target function +
  • +
  • env + table + new function environment +
  • +
+ + + + + +
+
+ + typesplit +
+
+ Split a typespec string into a table of normalized type names. + + +
    +
  • either + string or table + "?bool|:nometa" or {"boolean", ":nometa"} +
  • +
+ + + + + +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.functional.html b/modules/std.functional.html new file mode 100644 index 0000000..f5eeda1 --- /dev/null +++ b/modules/std.functional.html @@ -0,0 +1,1030 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.functional

+

Functional programming.

+

A selection of higher-order functions to enable a functional style of + programming in Lua.

+ + +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bind (fn, argt)Partially apply a function.
callable (x)Identify callable types.
case (with, branches)A rudimentary case statement.
collect ([ifn=std.npairs], ...)Collect the results of an iterator.
compose (...)Compose functions.
cond (expr, branch, ...)A rudimentary condition-case statement.
curry (fn, n)Curry a function.
filter (pfn[, ifn=std.pairs], ...)Filter an iterator with a predicate.
foldl (fn[, d=t[1]], t)Fold a binary function left associatively.
foldr (fn[, d=t[1]], t)Fold a binary function right associatively.
id (...)Identity function.
lambda (s)Compile a lambda string into a Lua function.
map (fn[, ifn=std.pairs], ...)Map a function over an iterator.
map_with (fn, tt)Map a function over a table of argument lists.
memoize (fn[, normfn=std.tostring])Memoize a function, by wrapping it in a functable.
nop ()No operation.
reduce (fn, d[, ifn=std.pairs], ...)Fold a binary function into an iterator.
zip (tt)Zip a table of tables.
zip_with (fn, tt)Zip a list of tables together with a function.
+

Types

+ + + + + + + + + +
normalize (...)Signature of a memoize argument normalization callback function.
predicate (...)Signature of a filter predicate callback function.
+ +
+
+ + +

Functions

+ Methods +
+
+ + bind (fn, argt) +
+
+ Partially apply a function. + + +

Parameters:

+
    +
  • fn + func + function to apply partially +
  • +
  • argt + table + table of fn arguments to bind +
  • +
+ +

Returns:

+
    + + function with argt arguments already bound +
+ + + +

Usage:

+
    +
    cube = bind (std.operator.pow, {[2] = 3})
    +
+ +
+
+ + callable (x) +
+
+ Identify callable types. + + +

Parameters:

+
    +
  • x + an object or primitive +
  • +
+ +

Returns:

+
    + + true if x can be called, otherwise false +
+ + + +

Usage:

+
    +
    if callable (functable) then functable (args) end
    +
+ +
+
+ + case (with, branches) +
+
+ A rudimentary case statement. + Match with against keys in branches table. + + +

Parameters:

+
    +
  • with + expression to match +
  • +
  • branches + table + map possible matches to functions +
  • +
+ +

Returns:

+
    + + the value associated with a matching key, or the first non-key + value if no key matches. Function or functable valued matches are + called using with as the sole argument, and the result of that call + returned; otherwise the matching value associated with the matching + key is returned directly; or else nil if there is no match and no + default. +
+ + +

See also:

+ + +

Usage:

+
    +
    + return case (type (object), {
    +   table  = "table",
    +   string = function ()  return "string" end,
    +            function (s) error ("unhandled type: " .. s) end,
    + })
    +
+ +
+
+ + collect ([ifn=std.npairs], ...) +
+
+ Collect the results of an iterator. + + +

Parameters:

+
    +
  • ifn + func + iterator function + (default std.npairs) +
  • +
  • ... + ifn arguments +
  • +
+ +

Returns:

+
    + + table + of results from running ifn on args +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {"a", "b", "c"}
    + collect {"a", "b", "c", x=1, y=2, z=5}
    +
+ +
+
+ + compose (...) +
+
+ Compose functions. + + +

Parameters:

+
    +
  • ... + func + functions to compose +
  • +
+ +

Returns:

+
    + + function + composition of fnN .. fn1: note that this is the + reverse of what you might expect, but means that code like:

    + +
     functional.compose (function (x) return f (x) end,
    +                     function (x) return g (x) end))
    +
    + +

    can be read from top to bottom. +

+ + + +

Usage:

+
    +
    + vpairs = compose (table.invert, ipairs)
    + for v, i in vpairs {"a", "b", "c"} do process (v, i) end
    +
+ +
+
+ + cond (expr, branch, ...) +
+
+ A rudimentary condition-case statement. + If expr is "truthy" return branch if given, otherwise expr + itself. If the return value is a function or functable, then call it + with expr as the sole argument and return the result; otherwise + return it explicitly. If expr is "falsey", then recurse with the + first two arguments stripped. + + +

Parameters:

+
    +
  • expr + a Lua expression +
  • +
  • branch + a function, functable or value to use if expr is + "truthy" +
  • +
  • ... + additional arguments to retry if expr is "falsey" +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    + -- recursively calculate the nth triangular number
    + function triangle (n)
    +   return cond (
    +     n <= 0, 0,
    +     n == 1, 1,
    +             function () return n + triangle (n - 1) end)
    + end
    +
+ +
+
+ + curry (fn, n) +
+
+ Curry a function. + + +

Parameters:

+
    +
  • fn + func + function to curry +
  • +
  • n + int + number of arguments +
  • +
+ +

Returns:

+
    + + function + curried version of fn +
+ + + +

Usage:

+
    +
    + add = curry (function (x, y) return x + y end, 2)
    + incr, decr = add (1), add (-1)
    +
+ +
+
+ + filter (pfn[, ifn=std.pairs], ...) +
+
+ Filter an iterator with a predicate. + + +

Parameters:

+
    +
  • pfn + predicate + predicate function +
  • +
  • ifn + func + iterator function + (default std.pairs) +
  • +
  • ... + iterator arguments +
  • +
+ +

Returns:

+
    + + table + elements e for which pfn (e) is not "falsey". +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {2, 4}
    + filter (lambda '|e|e%2==0', std.elems, {1, 2, 3, 4})
    +
+ +
+
+ + foldl (fn[, d=t[1]], t) +
+
+ Fold a binary function left associatively. + If parameter d is omitted, the first element of t is used, + and t treated as if it had been passed without that element. + + +

Parameters:

+
    +
  • fn + func + binary function +
  • +
  • d + initial left-most argument + (default t[1]) +
  • +
  • t + table + a table +
  • +
+ +

Returns:

+
    + + result +
+ + +

See also:

+ + +

Usage:

+
    +
    foldl (std.operator.quot, {10000, 100, 10}) == (10000 / 100) / 10
    +
+ +
+
+ + foldr (fn[, d=t[1]], t) +
+
+ Fold a binary function right associatively. + If parameter d is omitted, the last element of t is used, + and t treated as if it had been passed without that element. + + +

Parameters:

+
    +
  • fn + func + binary function +
  • +
  • d + initial right-most argument + (default t[1]) +
  • +
  • t + table + a table +
  • +
+ +

Returns:

+
    + + result +
+ + +

See also:

+ + +

Usage:

+
    +
    foldr (std.operator.quot, {10000, 100, 10}) == 10000 / (100 / 10)
    +
+ +
+
+ + id (...) +
+
+ Identity function. + + +

Parameters:

+
    +
  • ... + arguments +
  • +
+ +

Returns:

+
    + + arguments +
+ + + + +
+
+ + lambda (s) +
+
+ Compile a lambda string into a Lua function.

+ +

A valid lambda string takes one of the following forms:

+ +
    +
  1. '=expression': equivalent to function (...) return expression end
  2. +
  3. '|args|expression': equivalent to function (args) return expression end
  4. +
+ +

The first form (starting with '=') automatically assigns the first + nine arguments to parameters '_1' through '_9' for use within the + expression body. The parameter '_1' is aliased to '_', and if the + first non-whitespace of the whole expression is '_', then the + leading '=' can be omitted.

+ +

The results are memoized, so recompiling a previously compiled + lambda string is extremely fast. + + +

Parameters:

+
    +
  • s + string + a lambda string +
  • +
+ +

Returns:

+
    + + functable + compiled lambda string, can be called like a function +
+ + + +

Usage:

+
    +
    + -- The following are equivalent:
    + lambda '= _1 < _2'
    + lambda '|a,b| a<b'
    +
+ +
+
+ + map (fn[, ifn=std.pairs], ...) +
+
+ Map a function over an iterator. + + +

Parameters:

+
    +
  • fn + func + map function +
  • +
  • ifn + func + iterator function + (default std.pairs) +
  • +
  • ... + iterator arguments +
  • +
+ +

Returns:

+
    + + table + results +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {1, 4, 9, 16}
    + map (lambda '=_1*_1', std.ielems, {1, 2, 3, 4})
    +
+ +
+
+ + map_with (fn, tt) +
+
+ Map a function over a table of argument lists. + + +

Parameters:

+
    +
  • fn + func + map function +
  • +
  • tt + table + a table of fn argument lists +
  • +
+ +

Returns:

+
    + + table + new table of fn results +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {"123", "45"}, {a="123", b="45"}
    + conc = bind (map_with, {lambda '|...|table.concat {...}'})
    + conc {{1, 2, 3}, {4, 5}}, conc {a={1, 2, 3, x="y"}, b={4, 5, z=6}}
    +
+ +
+
+ + memoize (fn[, normfn=std.tostring]) +
+
+ Memoize a function, by wrapping it in a functable.

+ +

To ensure that memoize always returns the same results for the same + arguments, it passes arguments to fn. You can specify a more + sophisticated function if memoize should handle complicated argument + equivalencies. + + +

Parameters:

+
    +
  • fn + func + pure function: a function with no side effects +
  • +
  • normfn + normalize + function to normalize arguments + (default std.tostring) +
  • +
+ +

Returns:

+
    + + functable + memoized function +
+ + + +

Usage:

+
    +
    local fast = memoize (function (...) --[[ slow code ]] end)
    +
+ +
+
+ + nop () +
+
+ No operation. + This function ignores all arguments, and returns no values. + + + + + +

See also:

+ + +

Usage:

+
    +
    if unsupported then vtable["memrmem"] = nop end
    +
+ +
+
+ + reduce (fn, d[, ifn=std.pairs], ...) +
+
+ Fold a binary function into an iterator. + + +

Parameters:

+
    +
  • fn + func + reduce function +
  • +
  • d + initial first argument +
  • +
  • ifn + func + iterator function + (default std.pairs) +
  • +
  • ... + iterator arguments +
  • +
+ +

Returns:

+
    + + result +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> 2 ^ 3 ^ 4 ==> 4096
    + reduce (std.operator.pow, 2, std.ielems, {3, 4})
    +
+ +
+
+ + zip (tt) +
+
+ Zip a table of tables. + Make a new table, with lists of elements at the same index in the + original table. This function is effectively its own inverse. + + +

Parameters:

+
    +
  • tt + table + a table of tables +
  • +
+ +

Returns:

+
    + + table + new table with lists of elements of the same key + from tt +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {{1, 3, 5}, {2, 4}}, {a={x=1, y=3, z=5}, b={x=2, y=4}}
    + zip {{1, 2}, {3, 4}, {5}}, zip {x={a=1, b=2}, y={a=3, b=4}, z={a=5}}
    +
+ +
+
+ + zip_with (fn, tt) +
+
+ Zip a list of tables together with a function. + + +

Parameters:

+
    +
  • fn + function + function +
  • +
  • tt + table + table of tables +
  • +
+ +

Returns:

+
    + + table + a new table of results from calls to fn with arguments + made from all elements the same key in the original tables; effectively + the "columns" in a simple list + of lists. +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {"135", "24"}, {a="1", b="25"}
    + conc = bind (zip_with, {lambda '|...|table.concat {...}'})
    + conc {{1, 2}, {3, 4}, {5}}, conc {{a=1, b=2}, x={a=3, b=4}, {b=5}}
    +
+ +
+
+

Types

+ + +
+
+ + normalize (...) +
+
+ Signature of a memoize argument normalization callback function. + + +

Parameters:

+
    +
  • ... + arguments +
  • +
+ +

Returns:

+
    + + string + normalized arguments +
+ + + +

Usage:

+
    +
    + local normalize = function (name, value, props) return name end
    + local intern = std.functional.memoize (mksymbol, normalize)
    +
+ +
+
+ + predicate (...) +
+
+ Signature of a filter predicate callback function. + + +

Parameters:

+
    +
  • ... + arguments +
  • +
+ +

Returns:

+
    + + boolean + "truthy" if the predicate condition succeeds, + "falsey" otherwise +
+ + + +

Usage:

+
    +
    + local predicate = lambda '|k,v|type(v)=="string"'
    + local strvalues = filter (predicate, std.pairs, {name="Roberto", id=12345})
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.html b/modules/std.html new file mode 100644 index 0000000..40f7de8 --- /dev/null +++ b/modules/std.html @@ -0,0 +1,850 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std

+

Lua Standard Libraries.

+

This module contains a selection of improved Lua core functions, among + others.

+ +

Also, after requiring this module, simply referencing symbols in the + submodule hierarchy will load the necessary modules on demand.

+ +

By default there are no changes to any global symbols, or monkey + patching of core module tables and metatables. However, sometimes it's + still convenient to do that: For example, when using stdlib from the + REPL, or in a prototype where you want to throw caution to the wind and + compatibility with other modules be damned. In that case, you can give + stdlib permission to scribble all over your namespaces by using the + various monkey_patch calls in the library.

+ + +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
assert (expect[, f=""[, ...]])Enhance core assert to also allow formatted arguments.
barrel ([namespace=_G])A barrel of monkey_patches.
elems (t)An iterator over all elements of a sequence.
eval (s)Evaluate a string as Lua code.
getmetamethod (x, n)Return named metamethod, if any, otherwise nil.
ielems (t)An iterator over the integer keyed elements of a sequence.
ipairs (t)An iterator over elements of a sequence, until the first nil value.
ireverse (t)Return a new table with element order reversed.
monkey_patch ([namespace=_G])Overwrite core methods and metamethods with std enhanced versions.
npairs (t)Ordered iterator for integer keyed values.
pairs (t)Enhance core pairs to respect __pairs even in Lua 5.1.
require (module[, min[, too_big[, pattern]]])Enhance core require to assert version number compatibility.
ripairs (t)An iterator like ipairs, but in reverse.
rnpairs (t)An iterator like npairs, but in reverse.
tostring (x)Enhance core tostring to render table contents as a string.
+

Tables

+ + + + + +
stdModule table.
+

Metamethods

+ + + + + +
__index (name)Lazy loading of stdlib modules.
+ +
+
+ + +

Functions

+ Methods +
+
+ + assert (expect[, f=""[, ...]]) +
+
+ Enhance core assert to also allow formatted arguments. + + +

Parameters:

+
    +
  • expect + expression, expected to be truthy +
  • +
  • f + string + format string + (default "") +
  • +
  • ... + arguments to format + (optional) +
  • +
+ +

Returns:

+
    + + value of expect, if truthy +
+ + + +

Usage:

+
    +
    + std.assert (expected ~= nil, "100% unexpected!")
    + std.assert (expected ~= nil, "%s unexpected!", expected)
    +
+ +
+
+ + barrel ([namespace=_G]) +
+
+ A barrel of monkey_patches.

+ +

Apply all monkey_patch functions. Additionally, for backwards + compatibility only, write a selection of sub-module functions into + the given namespace. + + +

Parameters:

+
    +
  • namespace + table + where to install global functions + (default _G) +
  • +
+ +

Returns:

+
    + + table + module table +
+ + + +

Usage:

+
    +
    local std = require "std".barrel ()
    +
+ +
+
+ + elems (t) +
+
+ An iterator over all elements of a sequence. + If t has a __pairs metamethod, use that to iterate. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + table + t, the table being iterated over
  4. +
  5. + key, the previous iteration key
  6. +
+ + +

See also:

+ + +

Usage:

+
    +
    for value in std.elems {a = 1, b = 2, c = 5} do process (value) end
    +
+ +
+
+ + eval (s) +
+
+ Evaluate a string as Lua code. + + +

Parameters:

+
    +
  • s + string + string of Lua code +
  • +
+ +

Returns:

+
    + + result of evaluating s +
+ + + +

Usage:

+
    +
    std.eval "math.min (2, 10)"
    +
+ +
+
+ + getmetamethod (x, n) +
+
+ Return named metamethod, if any, otherwise nil. + + +

Parameters:

+
    +
  • x + item to act on +
  • +
  • n + string + name of metamethod to lookup +
  • +
+ +

Returns:

+
    + + function or nil + metamethod function, or nil if no metamethod +
+ + + +

Usage:

+
    +
    lookup = std.getmetamethod (require "std.object", "__index")
    +
+ +
+
+ + ielems (t) +
+
+ An iterator over the integer keyed elements of a sequence. + If t has a __len metamethod, iterate up to the index it returns. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + table + t, the table being iterated over
  4. +
  5. + int + index, the previous iteration index
  6. +
+ + +

See also:

+ + +

Usage:

+
    +
    for v in std.ielems {"a", "b", "c"} do process (v) end
    +
+ +
+
+ + ipairs (t) +
+
+ An iterator over elements of a sequence, until the first nil value.

+ +

Like Lua 5.1 and 5.3, but unlike Lua 5.2 (which looks for and uses the + __ipairs metamethod), this iterator returns successive key-value + pairs with integer keys starting at 1, up to the first nil valued + pair. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + table + t, the table being iterated over
  4. +
  5. + int + index, the previous iteration index
  6. +
+ + +

See also:

+ + +

Usage:

+
    +
    + -- length of sequence
    + args = {"first", "second", nil, "last"}
    + --> 1=first
    + --> 2=second
    + for i, v in std.ipairs (args) do
    +   print (string.format ("%d=%s", i, v))
    + end
    +
+ +
+
+ + ireverse (t) +
+
+ Return a new table with element order reversed. + Apart from the order of the elments returned, this function follows + the same rules as ipairs for determining first and last elements. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    + + table + a new table with integer keyed elements in reverse + order with respect to t +
+ + +

See also:

+ + +

Usage:

+
    +
    + local rielems = std.functional.compose (std.ireverse, std.ielems)
    + for e in rielems (l) do process (e) end
    +
+ +
+
+ + monkey_patch ([namespace=_G]) +
+
+ Overwrite core methods and metamethods with std enhanced versions.

+ +

Write all functions from this module, except std.barrel and + std.monkey_patch, into the given namespace. + + +

Parameters:

+
    +
  • namespace + table + where to install global functions + (default _G) +
  • +
+ +

Returns:

+
    + + table + the module table +
+ + + +

Usage:

+
    +
    local std = require "std".monkey_patch ()
    +
+ +
+
+ + npairs (t) +
+
+ Ordered iterator for integer keyed values. + Like ipairs, but does not stop until the largest integer key. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + table + t
  4. +
+ + +

See also:

+ + +

Usage:

+
    +
    for i,v in npairs {"one", nil, "three"} do ... end
    +
+ +
+
+ + pairs (t) +
+
+ Enhance core pairs to respect __pairs even in Lua 5.1. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + table + t, the table being iterated over
  4. +
  5. + key, the previous iteration key
  6. +
+ + +

See also:

+ + +

Usage:

+
    +
    for k, v in pairs {"a", b = "c", foo = 42} do process (k, v) end
    +
+ +
+
+ + require (module[, min[, too_big[, pattern]]]) +
+
+ Enhance core require to assert version number compatibility. + By default match against the last substring of (dot-delimited) + digits in the module version string. + + +

Parameters:

+
    +
  • module + string + module to require +
  • +
  • min + string + lowest acceptable version + (optional) +
  • +
  • too_big + string + lowest version that is too big + (optional) +
  • +
  • pattern + string + to match version in module.version or + module._VERSION (default: "([%.%d]+)%D*$") + (optional) +
  • +
+ + + + +

Usage:

+
    +
    + -- posix.version == "posix library for Lua 5.2 / 32"
    + posix = require ("posix", "29")
    +
+ +
+
+ + ripairs (t) +
+
+ An iterator like ipairs, but in reverse. + Apart from the order of the elments returned, this function follows + the same rules as ipairs for determining first and last elements. + + +

Parameters:

+
    +
  • t + table + any table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + table + t
  4. +
  5. + number + #t + 1
  6. +
+ + +

See also:

+ + +

Usage:

+
    +
    for i, v = ripairs (t) do ... end
    +
+ +
+
+ + rnpairs (t) +
+
+ An iterator like npairs, but in reverse. + Apart from the order of the elments returned, this function follows + the same rules as npairs for determining first and last elements. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    +
  1. + function + iterator function
  2. +
  3. + table + t
  4. +
+ + +

See also:

+ + +

Usage:

+
    +
    for i,v in rnpairs {"one", nil, "three"} do ... end
    +
+ +
+
+ + tostring (x) +
+
+ Enhance core tostring to render table contents as a string. + + +

Parameters:

+
    +
  • x + object to convert to string +
  • +
+ +

Returns:

+
    + + string + compact string rendering of x +
+ + + +

Usage:

+
    +
    + -- {1=baz,foo=bar}
    + print (std.tostring {foo="bar","baz"})
    +
+ +
+
+

Tables

+ +
+
+ + std +
+
+ Module table.

+ +

In addition to the functions documented on this page, and a version + field, references to other submodule functions will be loaded on + demand. + + +

Fields:

+
    +
  • version + release version string +
  • +
+ + + + + +
+
+

Metamethods

+ + +
+
+ + __index (name) +
+
+ Lazy loading of stdlib modules. + Don't load everything on initial startup, wait until first attempt + to access a submodule, and then load it on demand. + + +

Parameters:

+
    +
  • name + string + submodule name +
  • +
+ +

Returns:

+
    + + table or nil + the submodule that was loaded to satisfy the missing + name, otherwise nil if nothing was found +
+ + + +

Usage:

+
    +
    + local std = require "std"
    + local prototype = std.object.prototype
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.io.html b/modules/std.io.html new file mode 100644 index 0000000..f69b83a --- /dev/null +++ b/modules/std.io.html @@ -0,0 +1,618 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.io

+

Additions to the core io module.

+

+ + +

The module table returned by std.io also contains all of the entries from + the core io module table. An hygienic way to import this module, then, + is simply to override core io locally:

+ + +
+local io = require "std.io"
+
+ +

+ + +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
catdir (...)Concatenate directory names into a path.
catfile (...)Concatenate one or more directories and a filename into a path.
die (msg, ...)Die with error.
dirname (path)Remove the last dirsep delimited element from a path.
monkey_patch ([namespace=_G])Overwrite core io methods with std enhanced versions.
process_files (fn)Process files specified on the command-line.
readlines ([file=io.input()])Read a file or file handle into a list of lines.
shell (c)Perform a shell command and return its output.
slurp ([file=io.input()])Slurp a file handle.
splitdir (path)Split a directory path into components.
warn (msg, ...)Give warning with the name of program and file (if any).
writelines ([h=io.output()], ...)Write values adding a newline after each.
+

Types

+ + + + + +
fileprocessor (filename, i)Signature of process_files callback function.
+ +
+
+ + +

Functions

+ Methods +
+
+ + catdir (...) +
+
+ Concatenate directory names into a path. + + +

Parameters:

+
    +
  • ... + string + path components +
  • +
+ +

Returns:

+
    + + path without trailing separator +
+ + +

See also:

+ + +

Usage:

+
    +
    dirpath = catdir ("", "absolute", "directory")
    +
+ +
+
+ + catfile (...) +
+
+ Concatenate one or more directories and a filename into a path. + + +

Parameters:

+
    +
  • ... + string + path components +
  • +
+ +

Returns:

+
    + + string + path +
+ + +

See also:

+ + +

Usage:

+
    +
    filepath = catfile ("relative", "path", "filename")
    +
+ +
+
+ + die (msg, ...) +
+
+ Die with error. + This function uses the same rules to build a message prefix + as warn. + + +

Parameters:

+
    +
  • msg + string + format string +
  • +
  • ... + additional arguments to plug format string specifiers +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    die ("oh noes! (%s)", tostring (obj))
    +
+ +
+
+ + dirname (path) +
+
+ Remove the last dirsep delimited element from a path. + + +

Parameters:

+
    +
  • path + string + file path +
  • +
+ +

Returns:

+
    + + string + a new path with the last dirsep and following + truncated +
+ + + +

Usage:

+
    +
    dir = dirname "/base/subdir/filename"
    +
+ +
+
+ + monkey_patch ([namespace=_G]) +
+
+ Overwrite core io methods with std enhanced versions.

+ +

Also adds readlines and writelines metamethods to core file objects. + + +

Parameters:

+
    +
  • namespace + table + where to install global functions + (default _G) +
  • +
+ +

Returns:

+
    + + table + the std.io module table +
+ + + +

Usage:

+
    +
    local io = require "std.io".monkey_patch ()
    +
+ +
+
+ + process_files (fn) +
+
+ Process files specified on the command-line. + Each filename is made the default input source with io.input, and + then the filename and argument number are passed to the callback + function. In list of filenames, - means io.stdin. If no + filenames were given, behave as if a single - was passed. + + +

Parameters:

+
    +
  • fn + fileprocessor + function called for each file argument +
  • +
+ + + + +

Usage:

+
    +
    + #! /usr/bin/env lua
    + -- minimal cat command
    + local io = require "std.io"
    + io.process_files (function () io.write (io.slurp ()) end)
    +
+ +
+
+ + readlines ([file=io.input()]) +
+
+ Read a file or file handle into a list of lines. + The lines in the returned list are not \n terminated. + + +

Parameters:

+
    +
  • file + file or string + file handle or name; + if file is a file handle, that file is closed after reading + (default io.input()) +
  • +
+ +

Returns:

+
    + + list + lines +
+ + + +

Usage:

+
    +
    list = readlines "/etc/passwd"
    +
+ +
+
+ + shell (c) +
+
+ Perform a shell command and return its output. + + +

Parameters:

+ + +

Returns:

+
    + + string + output, or nil if error +
+ + +

See also:

+ + +

Usage:

+
    +
    users = shell [[cat /etc/passwd | awk -F: '{print $1;}']]
    +
+ +
+
+ + slurp ([file=io.input()]) +
+
+ Slurp a file handle. + + +

Parameters:

+
    +
  • file + file or string + file handle or name; + if file is a file handle, that file is closed after reading + (default io.input()) +
  • +
+ +

Returns:

+
    + + contents of file or handle, or nil if error +
+ + +

See also:

+ + +

Usage:

+
    +
    contents = slurp (filename)
    +
+ +
+
+ + splitdir (path) +
+
+ Split a directory path into components. + Empty components are retained: the root directory becomes {"", ""}. + + +

Parameters:

+
    +
  • path + path +
  • +
+ +

Returns:

+
    + + list of path components +
+ + +

See also:

+ + +

Usage:

+
    +
    dir_components = splitdir (filepath)
    +
+ +
+
+ + warn (msg, ...) +
+
+ Give warning with the name of program and file (if any). + If there is a global prog table, prefix the message with + prog.name or prog.file, and prog.line if any. Otherwise + if there is a global opts table, prefix the message with + opts.program and opts.line if any. std.optparse:parse + returns an opts table that provides the required program + field, as long as you assign it back to _G.opts. + + +

Parameters:

+
    +
  • msg + string + format string +
  • +
  • ... + additional arguments to plug format string specifiers +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    +   local OptionParser = require "std.optparse"
    +   local parser = OptionParser "eg 0\nUsage: eg\n"
    +   _G.arg, _G.opts = parser:parse (_G.arg)
    +   if not _G.opts.keep_going then
    +     require "std.io".warn "oh noes!"
    +   end
    +
+ +
+
+ + writelines ([h=io.output()], ...) +
+
+ Write values adding a newline after each. + + +

Parameters:

+
    +
  • h + file + open writable file handle; + the file is not closed after writing + (default io.output()) +
  • +
  • ... + string or number + values to write (as for write) +
  • +
+ + + + +

Usage:

+
    +
    writelines (io.stdout, "first line", "next line")
    +
+ +
+
+

Types

+ + +
+
+ + fileprocessor (filename, i) +
+
+ Signature of process_files callback function. + + +

Parameters:

+
    +
  • filename + string + filename +
  • +
  • i + int + argument number of filename +
  • +
+ + + + +

Usage:

+
    +
    + local fileprocessor = function (filename, i)
    +   io.write (tostring (i) .. ":\n===\n" .. io.slurp (filename) .. "\n")
    + end
    + io.process_files (fileprocessor)
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.math.html b/modules/std.math.html new file mode 100644 index 0000000..8fd2b94 --- /dev/null +++ b/modules/std.math.html @@ -0,0 +1,222 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.math

+

Additions to the core math module.

+

+ + +

The module table returned by std.math also contains all of the entries from + the core math table. An hygienic way to import this module, then, is simply + to override the core math locally:

+ + +
+local math = require "std.math"
+
+ +

+ + +

Functions

+ + + + + + + + + + + + + +
floor (n[, p=0])Extend math.floor to take the number of decimal places.
monkey_patch ([namespace=_G])Overwrite core math methods with std enhanced versions.
round (n[, p=0])Round a number to a given number of decimal places
+ +
+
+ + +

Functions

+ Methods +
+
+ + floor (n[, p=0]) +
+
+ Extend math.floor to take the number of decimal places. + + +

Parameters:

+
    +
  • n + number + number +
  • +
  • p + int + number of decimal places to truncate to + (default 0) +
  • +
+ +

Returns:

+
    + + number + n truncated to p decimal places +
+ + + +

Usage:

+
    +
    tenths = floor (magnitude, 1)
    +
+ +
+
+ + monkey_patch ([namespace=_G]) +
+
+ Overwrite core math methods with std enhanced versions. + + +

Parameters:

+
    +
  • namespace + table + where to install global functions + (default _G) +
  • +
+ +

Returns:

+
    + + table + the module table +
+ + + +

Usage:

+
    +
    require "std.math".monkey_patch ()
    +
+ +
+
+ + round (n[, p=0]) +
+
+ Round a number to a given number of decimal places + + +

Parameters:

+
    +
  • n + number + number +
  • +
  • p + int + number of decimal places to round to + (default 0) +
  • +
+ +

Returns:

+
    + + number + n rounded to p decimal places +
+ + + +

Usage:

+
    +
    roughly = round (exactly, 2)
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.operator.html b/modules/std.operator.html new file mode 100644 index 0000000..0ebf53f --- /dev/null +++ b/modules/std.operator.html @@ -0,0 +1,755 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.operator

+

Functional forms of Lua operators.

+

+ +

+ + +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
concat (a, b)Stringify and concatenate arguments.
conj (a, b)Return the logical conjunction of the arguments.
diff (a, b)Return the difference of the arguments.
disj (a, b)Return the logical disjunction of the arguments.
eq (a, b)Return the equality of the arguments.
get (t, k)Dereference a table.
gt (a, b)Return whether the arguments are in descending order.
gte (a, b)Return whether the arguments are not in ascending order.
lt (a, b)Return whether the arguments are in ascending order.
lte (a, b)Return whether the arguments are not in descending order.
mod (a, b)Return the modulus of the arguments.
neg (a)Return the logical negation of the arguments.
neq (a, b)Return the inequality of the arguments.
pow (a, b)Return the exponent of the arguments.
prod (a, b)Return the product of the arguments.
quot (a, b)Return the quotient of the arguments.
set (t, k, v)Set a table element, honoring metamethods.
sum (a, b)Return the sum of the arguments.
+ +
+
+ + +

Functions

+ Methods +
+
+ + concat (a, b) +
+
+ Stringify and concatenate arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + concatenation of stringified arguments. +
+ + + +

Usage:

+
    +
    + --> "=> 1000010010"
    + functional.foldl (concat, "=> ", {10000, 100, 10})
    +
+ +
+
+ + conj (a, b) +
+
+ Return the logical conjunction of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + logical a and b +
+ + + +

Usage:

+
    +
    + --> true
    + functional.foldl (conj, {true, 1, "false"})
    +
+ +
+
+ + diff (a, b) +
+
+ Return the difference of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + the difference between a and b +
+ + + +

Usage:

+
    +
    + --> 890
    + functional.foldl (diff, {10000, 100, 10})
    +
+ +
+
+ + disj (a, b) +
+
+ Return the logical disjunction of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + logical a or b +
+ + + +

Usage:

+
    +
    + --> true
    + functional.foldl (disj, {true, 1, false})
    +
+ +
+
+ + eq (a, b) +
+
+ Return the equality of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + true if a is b, otherwise false +
+ + + + +
+
+ + get (t, k) +
+
+ Dereference a table. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
  • k + a key to lookup in t +
  • +
+ +

Returns:

+
    + + value stored at t[k] if any, otherwise nil +
+ + + +

Usage:

+
    +
    + --> 4
    + functional.foldl (get, {1, {{2, 3, 4}, 5}}, {2, 1, 3})
    +
+ +
+
+ + gt (a, b) +
+
+ Return whether the arguments are in descending order. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + true if a is greater then b, otherwise false +
+ + + + +
+
+ + gte (a, b) +
+
+ Return whether the arguments are not in ascending order. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + true if a is not greater then b, otherwise false +
+ + + + +
+
+ + lt (a, b) +
+
+ Return whether the arguments are in ascending order. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + true if a is less then b, otherwise false +
+ + + + +
+
+ + lte (a, b) +
+
+ Return whether the arguments are not in descending order. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + true if a is not greater then b, otherwise false +
+ + + + +
+
+ + mod (a, b) +
+
+ Return the modulus of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + the modulus of a and b +
+ + + +

Usage:

+
    +
    + --> 3
    + functional.foldl (mod, {65536, 100, 11})
    +
+ +
+
+ + neg (a) +
+
+ Return the logical negation of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
+ +

Returns:

+
    + + not a +
+ + + +

Usage:

+
    +
    + --> {true, false, false, false}
    + functional.bind (functional.map, {std.ielems, neg}) {false, true, 1, 0}
    +
+ +
+
+ + neq (a, b) +
+
+ Return the inequality of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + false if a is b, otherwise true +
+ + + +

Usage:

+
    +
    + --> true
    + local f = require "std.functional"
    + table.empty (f.filter (f.bind (neq, {6}), std.ielems, {6, 6, 6})
    +
+ +
+
+ + pow (a, b) +
+
+ Return the exponent of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + the a to the power of b +
+ + + +

Usage:

+
    +
    + --> 4096
    + functional.foldl (pow, {2, 3, 4})
    +
+ +
+
+ + prod (a, b) +
+
+ Return the product of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + the product of a and b +
+ + + +

Usage:

+
    +
    + --> 10000000
    + functional.foldl (prod, {10000, 100, 10})
    +
+ +
+
+ + quot (a, b) +
+
+ Return the quotient of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + the quotient a and b +
+ + + +

Usage:

+
    +
    + --> 1000
    + functional.foldr (quot, {10000, 100, 10})
    +
+ +
+
+ + set (t, k, v) +
+
+ Set a table element, honoring metamethods. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
  • k + a key to lookup in t +
  • +
  • v + a value to set for k +
  • +
+ +

Returns:

+
    + + table + t +
+ + + +

Usage:

+
    +
    + -- destructive table merge:
    + --> {"one", bar="baz", two=5}
    + functional.reduce (set, {"foo", bar="baz"}, {"one", two=5})
    +
+ +
+
+ + sum (a, b) +
+
+ Return the sum of the arguments. + + +

Parameters:

+
    +
  • a + an argument +
  • +
  • b + another argument +
  • +
+ +

Returns:

+
    + + the sum of the a and b +
+ + + +

Usage:

+
    +
    + --> 10110
    + functional.foldl (sum, {10000, 100, 10})
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.package.html b/modules/std.package.html new file mode 100644 index 0000000..c1d7e16 --- /dev/null +++ b/modules/std.package.html @@ -0,0 +1,418 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.package

+

Additions to the core package module.

+

+ + +

The module table returned by std.package also contains all of the entries + from the core package table. An hygienic way to import this module, then, is + simply to override core package locally:

+ + +
+local package = require "std.package"
+
+ +

+ + +

Functions

+ + + + + + + + + + + + + + + + + + + + + +
find (pathstrings, patt[, init=1[, plain=false]])Look for a path segment match of patt in pathstrings.
insert (pathstrings[, pos=n+1], value)Insert a new element into a package.path like string of paths.
mappath (pathstrings, callback, ...)Call a function with each element of a path string.
normalize (...)Normalize a path list.
remove (pathstrings[, pos=n])Remove any element from a package.path like string of paths.
+

Tables

+ + + + + +
packageMake named constants for package.config + (undocumented in 5.1; see luaconf.h for C equivalents).
+

Types

+ + + + + +
mappathcb (element, ...)Function signature of a callback for mappath.
+ +
+
+ + +

Functions

+ Methods +
+
+ + find (pathstrings, patt[, init=1[, plain=false]]) +
+
+ Look for a path segment match of patt in pathstrings. + + +

Parameters:

+
    +
  • pathstrings + string + pathsep delimited path elements +
  • +
  • patt + string + a Lua pattern to search for in pathstrings +
  • +
  • init + int + element (not byte index!) to start search at. + Negative numbers begin counting backwards from the last element + (default 1) +
  • +
  • plain + bool + unless false, treat patt as a plain + string, not a pattern. Note that if plain is given, then init + must be given as well. + (default false) +
  • +
+ +

Returns:

+
    + + the matching element number (not byte index!) and full text + of the matching element, if any; otherwise nil +
+ + + +

Usage:

+
    +
    i, s = find (package.path, "^[^" .. package.dirsep .. "/]")
    +
+ +
+
+ + insert (pathstrings[, pos=n+1], value) +
+
+ Insert a new element into a package.path like string of paths. + + +

Parameters:

+
    +
  • pathstrings + string + a package.path like string +
  • +
  • pos + int + element index at which to insert value, where n is + the number of elements prior to insertion + (default n+1) +
  • +
  • value + string + new path element to insert +
  • +
+ +

Returns:

+
    + + string + a new string with the new element inserted +
+ + + +

Usage:

+
    +
    package.path = insert (package.path, 1, install_dir .. "/?.lua")
    +
+ +
+
+ + mappath (pathstrings, callback, ...) +
+
+ Call a function with each element of a path string. + + +

Parameters:

+
    +
  • pathstrings + string + a package.path like string +
  • +
  • callback + mappathcb + function to call for each element +
  • +
  • ... + additional arguments passed to callback +
  • +
+ +

Returns:

+
    + + nil, or first non-nil returned by callback +
+ + + +

Usage:

+
    +
    mappath (package.path, searcherfn, transformfn)
    +
+ +
+
+ + normalize (...) +
+
+ Normalize a path list. + Removing redundant . and .. directories, and keep only the first + instance of duplicate elements. Each argument can contain any number + of pathsep delimited elements; wherein characters are subject to + / and ? normalization, converting / to dirsep and ? to + path_mark (unless immediately preceded by a % character). + + +

Parameters:

+
    +
  • ... + path elements +
  • +
+ +

Returns:

+
    + + string + a single normalized pathsep delimited paths string +
+ + + +

Usage:

+
    +
    package.path = normalize (user_paths, sys_paths, package.path)
    +
+ +
+
+ + remove (pathstrings[, pos=n]) +
+
+ Remove any element from a package.path like string of paths. + + +

Parameters:

+
    +
  • pathstrings + string + a package.path like string +
  • +
  • pos + int + element index from which to remove an item, where n + is the number of elements prior to removal + (default n) +
  • +
+ +

Returns:

+
    + + string + a new string with given element removed +
+ + + +

Usage:

+
    +
    package.path = remove (package.path)
    +
+ +
+
+

Tables

+ +
+
+ + package +
+
+ Make named constants for package.config + (undocumented in 5.1; see luaconf.h for C equivalents). + + +

Fields:

+
    +
  • dirsep + string + directory separator +
  • +
  • pathsep + string + path separator +
  • +
  • path_mark + string + string that marks substitution points in a path template +
  • +
  • execdir + string + (Windows only) replaced by the executable's directory in a path +
  • +
  • igmark + string + Mark to ignore all before it when building luaopen_ function name. +
  • +
+ + + + + +
+
+

Types

+ + +
+
+ + mappathcb (element, ...) +
+
+ Function signature of a callback for mappath. + + +

Parameters:

+
    +
  • element + string + an element from a pathsep delimited string of + paths +
  • +
  • ... + additional arguments propagated from mappath +
  • +
+ +

Returns:

+
    + + non-nil to break, otherwise continue with the next element +
+ + + + +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.strict.html b/modules/std.strict.html new file mode 100644 index 0000000..ff52f9e --- /dev/null +++ b/modules/std.strict.html @@ -0,0 +1,161 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.strict

+

Checks uses of undeclared global variables.

+

All global variables must be 'declared' through a regular + assignment (even assigning nil will do) in a top-level + chunk before being used anywhere or assigned to inside a function.

+ +

To use this module, just require it near the start of your program.

+ +

From Lua distribution (etc/strict.lua).

+ + +

Functions

+ + + + + + + + + +
__index (t, n)Detect dereference of undeclared global.
__newindex (t, n, v)Detect assignment to undeclared global.
+ +
+
+ + +

Functions

+ Methods +
+
+ + __index (t, n) +
+
+ Detect dereference of undeclared global. + + +

Parameters:

+
    +
  • t + table + _G +
  • +
  • n + string + name of the variable being dereferenced +
  • +
+ + + + + +
+
+ + __newindex (t, n, v) +
+
+ Detect assignment to undeclared global. + + +

Parameters:

+
    +
  • t + table + _G +
  • +
  • n + string + name of the variable being declared +
  • +
  • v + initial value of the variable +
  • +
+ + + + + +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.string.html b/modules/std.string.html new file mode 100644 index 0000000..e04aad9 --- /dev/null +++ b/modules/std.string.html @@ -0,0 +1,1214 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.string

+

Additions to the core string module.

+

+ + +

The module table returned by std.string also contains all of the entries + from the core string table. An hygienic way to import this module, then, is + simply to override the core string locally:

+ + +
+local string = require "std.string"
+
+ +

+ + +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
caps (s)Capitalise each word in a string.
chomp (s)Remove any final newline from a string.
escape_pattern (s)Escape a string to be used as a pattern.
escape_shell (s)Escape a string to be used as a shell token.
finds (s, pattern[, init=1[, plain]])Repeatedly string.find until target string is exhausted.
format (f[, ...])Extend to work better with one argument.
ltrim (s[, r="%s+"])Remove leading matter from a string.
monkey_patch ([namespace=_G])Overwrite core string methods with std enhanced versions.
numbertosi (n)Write a number using SI suffixes.
ordinal_suffix (n)Return the English suffix for an ordinal.
pad (s, w[, p=" "])Justify a string.
prettytostring (x[, indent="\t"[, spacing=""]])Pretty-print a table, or other object.
render (x, open, close, elem, pair, sep[, roots])Turn tables into strings with recursion detection.
rtrim (s[, r="%s+"])Remove trailing matter from a string.
split (s[, sep="%s+"])Split a string at a given separator.
tfind (s, pattern[, init=1[, plain]])Do string.find, returning a table of captures.
trim (s[, r="%s+"])Remove leading and trailing matter from a string.
wrap (s[, w=78[, ind=0[, ind1=ind]]])Wrap a string into a paragraph.
+

Fields

+ + + + + + + + + + + + + +
__concatString concatenation operation.
__indexString subscript operation.
pickleConvert a value to a string.
+

Types

+ + + + + + + + + + + + + + + + + + + + + +
closetablecb (t)Signature of render close table callback.
elementcb (x)Signature of render element callback.
opentablecb (t)Signature of render open table callback.
paircb (t, key, value, keystr, valuestr)Signature of render pair callback.
separatorcb (t, pk, pv, fk, fv)Signature of render separator callback.
+ +
+
+ + +

Functions

+ Methods +
+
+ + caps (s) +
+
+ Capitalise each word in a string. + + +

Parameters:

+
    +
  • s + string + any string +
  • +
+ +

Returns:

+
    + + string + s with each word capitalized +
+ + + +

Usage:

+
    +
    userfullname = caps (input_string)
    +
+ +
+
+ + chomp (s) +
+
+ Remove any final newline from a string. + + +

Parameters:

+
    +
  • s + string + any string +
  • +
+ +

Returns:

+
    + + string + s with any single trailing newline removed +
+ + + +

Usage:

+
    +
    line = chomp (line)
    +
+ +
+
+ + escape_pattern (s) +
+
+ Escape a string to be used as a pattern. + + +

Parameters:

+
    +
  • s + string + any string +
  • +
+ +

Returns:

+
    + + string + s with active pattern characters escaped +
+ + + +

Usage:

+
    +
    substr = inputstr:match (escape_pattern (literal))
    +
+ +
+
+ + escape_shell (s) +
+
+ Escape a string to be used as a shell token. + Quotes spaces, parentheses, brackets, quotes, apostrophes and + whitespace. + + +

Parameters:

+
    +
  • s + string + any string +
  • +
+ +

Returns:

+
    + + string + s with active shell characters escaped +
+ + + +

Usage:

+
    +
    os.execute ("echo " .. escape_shell (outputstr))
    +
+ +
+
+ + finds (s, pattern[, init=1[, plain]]) +
+
+ Repeatedly string.find until target string is exhausted. + + +

Parameters:

+
    +
  • s + string + target string +
  • +
  • pattern + string + pattern to match in s +
  • +
  • init + int + start position + (default 1) +
  • +
  • plain + bool + inhibit magic characters + (optional) +
  • +
+ +

Returns:

+
    + + list of {from, to; capt = {captures}} +
+ + +

See also:

+ + +

Usage:

+
    +
    + for t in std.elems (finds ("the target string", "%S+")) do
    +   print (tostring (t.capt))
    + end
    +
+ +
+
+ + format (f[, ...]) +
+
+ Extend to work better with one argument. + If only one argument is passed, no formatting is attempted. + + +

Parameters:

+
    +
  • f + string + format string +
  • +
  • ... + arguments to format + (optional) +
  • +
+ +

Returns:

+
    + + formatted string +
+ + + +

Usage:

+
    +
    print (format "100% stdlib!")
    +
+ +
+
+ + ltrim (s[, r="%s+"]) +
+
+ Remove leading matter from a string. + + +

Parameters:

+
    +
  • s + string + any string +
  • +
  • r + string + leading pattern + (default "%s+") +
  • +
+ +

Returns:

+
    + + string + s with leading r stripped +
+ + + +

Usage:

+
    +
    print ("got: " .. ltrim (userinput))
    +
+ +
+
+ + monkey_patch ([namespace=_G]) +
+
+ Overwrite core string methods with std enhanced versions.

+ +

Also adds auto-stringification to .. operator on core strings, and + integer indexing of strings with [] dereferencing. + + +

Parameters:

+
    +
  • namespace + table + where to install global functions + (default _G) +
  • +
+ +

Returns:

+
    + + table + the module table +
+ + + +

Usage:

+
    +
    local string = require "std.string".monkey_patch ()
    +
+ +
+
+ + numbertosi (n) +
+
+ Write a number using SI suffixes. + The number is always written to 3 s.f. + + +

Parameters:

+
    +
  • n + number or string + any numeric value +
  • +
+ +

Returns:

+
    + + string + n simplifed using largest available SI suffix. +
+ + + +

Usage:

+
    +
    print (numbertosi (bitspersecond) .. "bps")
    +
+ +
+
+ + ordinal_suffix (n) +
+
+ Return the English suffix for an ordinal. + + +

Parameters:

+
    +
  • n + int or string + any integer value +
  • +
+ +

Returns:

+
    + + string + English suffix for n +
+ + + +

Usage:

+
    +
    + local now = os.date "*t"
    + print ("%d%s day of the week", now.day, ordinal_suffix (now.day))
    +
+ +
+
+ + pad (s, w[, p=" "]) +
+
+ Justify a string. + When the string is longer than w, it is truncated (left or right + according to the sign of w). + + +

Parameters:

+
    +
  • s + string + a string to justify +
  • +
  • w + int + width to justify to (-ve means right-justify; +ve means + left-justify) +
  • +
  • p + string + string to pad with + (default " ") +
  • +
+ +

Returns:

+
    + + string + s justified to w characters wide +
+ + + +

Usage:

+
    +
    print (pad (trim (outputstr, 78)) .. "\n")
    +
+ +
+
+ + prettytostring (x[, indent="\t"[, spacing=""]]) +
+
+ Pretty-print a table, or other object. + + +

Parameters:

+
    +
  • x + object to convert to string +
  • +
  • indent + string + indent between levels + (default "\t") +
  • +
  • spacing + string + space before every line + (default "") +
  • +
+ +

Returns:

+
    + + string + pretty string rendering of x +
+ + + +

Usage:

+
    +
    print (prettytostring (std, "  "))
    +
+ +
+
+ + render (x, open, close, elem, pair, sep[, roots]) +
+
+ Turn tables into strings with recursion detection. + N.B. Functions calling render should not recurse, or recursion + detection will not work. + + +

Parameters:

+
    +
  • x + object to convert to string +
  • +
  • open + opentablecb + open table rendering function +
  • +
  • close + closetablecb + close table rendering function +
  • +
  • elem + elementcb + element rendering function +
  • +
  • pair + paircb + pair rendering function +
  • +
  • sep + separatorcb + separator rendering function +
  • +
  • roots + table + accumulates table references to detect recursion + (optional) +
  • +
+ +

Returns:

+
    + + string representation of x +
+ + + +

Usage:

+
    +
    + function tostring (x)
    +   return render (x, lambda '="{"', lambda '="}"', tostring,
    +                  lambda '=_4.."=".._5', lambda '= _4 and "," or ""',
    +                  lambda '=","')
    + end
    +
+ +
+
+ + rtrim (s[, r="%s+"]) +
+
+ Remove trailing matter from a string. + + +

Parameters:

+
    +
  • s + string + any string +
  • +
  • r + string + trailing pattern + (default "%s+") +
  • +
+ +

Returns:

+
    + + string + s with trailing r stripped +
+ + + +

Usage:

+
    +
    print ("got: " .. rtrim (userinput))
    +
+ +
+
+ + split (s[, sep="%s+"]) +
+
+ Split a string at a given separator. + Separator is a Lua pattern, so you have to escape active characters, + ^$()%.[]*+-? with a % prefix to match a literal character in s. + + +

Parameters:

+
    +
  • s + string + to split +
  • +
  • sep + string + separator pattern + (default "%s+") +
  • +
+ +

Returns:

+
    + + list of strings +
+ + + +

Usage:

+
    +
    words = split "a very short sentence"
    +
+ +
+
+ + tfind (s, pattern[, init=1[, plain]]) +
+
+ Do string.find, returning a table of captures. + + +

Parameters:

+
    +
  • s + string + target string +
  • +
  • pattern + string + pattern to match in s +
  • +
  • init + int + start position + (default 1) +
  • +
  • plain + bool + inhibit magic characters + (optional) +
  • +
+ +

Returns:

+
    +
  1. + int + start of match
  2. +
  3. + int + end of match
  4. +
  5. + table + list of captured strings
  6. +
+ + +

See also:

+ + +

Usage:

+
    +
    b, e, captures = tfind ("the target string", "%s", 10)
    +
+ +
+
+ + trim (s[, r="%s+"]) +
+
+ Remove leading and trailing matter from a string. + + +

Parameters:

+
    +
  • s + string + any string +
  • +
  • r + string + trailing pattern + (default "%s+") +
  • +
+ +

Returns:

+
    + + string + s with leading and trailing r stripped +
+ + + +

Usage:

+
    +
    print ("got: " .. trim (userinput))
    +
+ +
+
+ + wrap (s[, w=78[, ind=0[, ind1=ind]]]) +
+
+ Wrap a string into a paragraph. + + +

Parameters:

+
    +
  • s + string + a paragraph of text +
  • +
  • w + int + width to wrap to + (default 78) +
  • +
  • ind + int + indent + (default 0) +
  • +
  • ind1 + int + indent of first line + (default ind) +
  • +
+ +

Returns:

+
    + + string + s wrapped to w columns +
+ + + +

Usage:

+
    +
    print (wrap (copyright, 72, 4))
    +
+ +
+
+

Fields

+ +
+
+ + __concat +
+
+ String concatenation operation. + + +
    +
  • s + string + initial string +
  • +
  • o + object to stringify and concatenate +
  • +
+ + + + +

Usage:

+
    +
    + local string = require "std.string".monkey_patch ()
    + concatenated = "foo" .. {"bar"}
    +
+ +
+
+ + __index +
+
+ String subscript operation. + + +
    +
  • s + string + string +
  • +
  • i + int or string + index or method name +
  • +
+ + + + +

Usage:

+
    +
    + getmetatable ("").__index = require "std.string".__index
    + third = ("12345")[3]
    +
+ +
+
+ + pickle +
+
+ Convert a value to a string. + The string can be passed to functional.eval to retrieve the value. + + +
    +
  • x + object to pickle +
  • +
+ + + +

See also:

+ + +

Usage:

+
    +
    function slow_identity (x) return functional.eval (pickle (x)) end
    +
+ +
+
+

Types

+ + +
+
+ + closetablecb (t) +
+
+ Signature of render close table callback. + + +

Parameters:

+
    +
  • t + table + table just rendered +
  • +
+ +

Returns:

+
    + + string + close table rendering +
+ + +

See also:

+ + +

Usage:

+
    +
    function close (t) return "}" end
    +
+ +
+
+ + elementcb (x) +
+
+ Signature of render element callback. + + +

Parameters:

+
    +
  • x + element to render +
  • +
+ +

Returns:

+
    + + string + element rendering +
+ + +

See also:

+ + +

Usage:

+
    +
    function element (e) return require "std".tostring (e) end
    +
+ +
+
+ + opentablecb (t) +
+
+ Signature of render open table callback. + + +

Parameters:

+
    +
  • t + table + table about to be rendered +
  • +
+ +

Returns:

+
    + + string + open table rendering +
+ + +

See also:

+ + +

Usage:

+
    +
    function open (t) return "{" end
    +
+ +
+
+ + paircb (t, key, value, keystr, valuestr) +
+
+ Signature of render pair callback. + Trying to re-render key or value here will break recursion + detection, use strkey and strvalue pre-rendered values instead. + + +

Parameters:

+
    +
  • t + table + table containing pair being rendered +
  • +
  • key + key part of key being rendered +
  • +
  • value + value part of key being rendered +
  • +
  • keystr + string + prerendered key +
  • +
  • valuestr + string + prerendered value +
  • +
+ +

Returns:

+
    + + string + pair rendering +
+ + +

See also:

+ + +

Usage:

+
    +
    function pair (_, _, _, key, value) return key .. "=" .. value end
    +
+ +
+
+ + separatorcb (t, pk, pv, fk, fv) +
+
+ Signature of render separator callback. + + +

Parameters:

+
    +
  • t + table + table currently being rendered +
  • +
  • pk + t key preceding separator, or nil for first key +
  • +
  • pv + t value preceding separator, or nil for first value +
  • +
  • fk + t key following separator, or nil for last key +
  • +
  • fv + t value following separator, or nil for last value +
  • +
+ +

Returns:

+
    + + string + separator rendering +
+ + + +

Usage:

+
    +
    function separator (_, _, _, fk) return fk and "," or "" end
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/modules/std.table.html b/modules/std.table.html new file mode 100644 index 0000000..2184872 --- /dev/null +++ b/modules/std.table.html @@ -0,0 +1,1172 @@ + + + + + stdlib 41.2.2 Reference + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module std.table

+

Extensions to the core table module.

+

+ + +

The module table returned by std.table also contains all of the entries from + the core table module. An hygienic way to import this module, then, is simply + to override the core table locally:

+ + +
+local table = require "std.table"
+
+ +

+ + +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
clone (t[, map={}[, nometa]])Make a shallow copy of a table, including any metatable.
clone_select (t[, keys={}[, nometa]])Make a partial clone of a table.
depair (ls)Turn a list of pairs into a table.
empty (t)Return whether table is empty.
enpair (t)Turn a table into a list of pairs.
flatten (t)Flatten a nested table into a list.
insert (t[, pos=len (t)], v)Enhance core table.insert to return its result.
invert (t)Invert a table.
keys (t)Make the list of keys in table.
len (t)Equivalent to # operation, but respecting __len even on Lua 5.1.
maxn (t)Largest integer key in a table.
merge (t, u[, map={}[, nometa]])Destructively merge another table's fields into another.
merge_select (t, u[, keys={}[, nometa]])Destructively merge another table's named fields into table.
monkey_patch ([namespace=_G])Overwrite core table methods with std enhanced versions.
new ([x=nil[, t={}]])Make a table with a default value for unset keys.
okeys (t)Make an ordered list of keys in table.
pack (...)Turn a tuple into a list.
project (fkey, tt)Project a list of fields from a list of tables.
remove (t[, pos=len (t)])Enhance core table.remove to respect __len when pos is omitted.
shape (dims, t)Shape a table according to a list of dimensions.
size (t)Find the number of elements in a table.
sort (t[, c=std.operator.lt])Enhance core table.sort to return its result.
unpack (t[, i=1[, j=table.maxn(t)]])Enhance core table.unpack to always unpack up to maxn (t).
values (t)Make the list of values of a table.
+

Types

+ + + + + +
comparator (a, b)Signature of a sort comparator function.
+ +
+
+ + +

Functions

+ Methods +
+
+ + clone (t[, map={}[, nometa]]) +
+
+ Make a shallow copy of a table, including any metatable.

+ +

To make deep copies, use tree.clone. + + +

Parameters:

+
    +
  • t + table + source table +
  • +
  • map + table + table of {old_key=new_key, ...} + (default {}) +
  • +
  • nometa + bool + if non-nil don't copy metatable + (optional) +
  • +
+ +

Returns:

+
    + + copy of t, also sharing t's metatable unless nometa + is true, and with keys renamed according to map +
+ + +

See also:

+ + +

Usage:

+
    +
    shallowcopy = clone (original, {rename_this = "to_this"}, ":nometa")
    +
+ +
+
+ + clone_select (t[, keys={}[, nometa]]) +
+
+ Make a partial clone of a table.

+ +

Like clone, but does not copy any fields by default. + + +

Parameters:

+
    +
  • t + table + source table +
  • +
  • keys + table + list of keys to copy + (default {}) +
  • +
  • nometa + bool + if non-nil don't copy metatable + (optional) +
  • +
+ +

Returns:

+
    + + table + copy of fields in selection from t, also sharing t's + metatable unless nometa +
+ + +

See also:

+ + +

Usage:

+
    +
    partialcopy = clone_select (original, {"this", "and_this"}, true)
    +
+ +
+
+ + depair (ls) +
+
+ Turn a list of pairs into a table. + + +

Parameters:

+
    +
  • ls + table + list of lists +
  • +
+ +

Returns:

+
    + + table + a flat table with keys and values from ls +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {a=1, b=2, c=3}
    + depair {{"a", 1}, {"b", 2}, {"c", 3}}
    +
+ +
+
+ + empty (t) +
+
+ Return whether table is empty. + + +

Parameters:

+
    +
  • t + table + any table +
  • +
+ +

Returns:

+
    + + boolean + true if t is empty, otherwise false +
+ + + +

Usage:

+
    +
    if empty (t) then error "ohnoes" end
    +
+ +
+
+ + enpair (t) +
+
+ Turn a table into a list of pairs. + + +

Parameters:

+
    +
  • t + table + a table {i1=v1, ..., in=vn} +
  • +
+ +

Returns:

+
    + + table + a new list of pairs containing {{i1, v1}, ..., {in, vn}} +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {{1, "a"}, {2, "b"}, {3, "c"}}
    + enpair {"a", "b", "c"}
    +
+ +
+
+ + flatten (t) +
+
+ Flatten a nested table into a list. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    + + table + a list of all non-table elements of t +
+ + + +

Usage:

+
    +
    + --> {1, 2, 3, 4, 5}
    + flatten {{1, {{2}, 3}, 4}, 5}
    +
+ +
+
+ + insert (t[, pos=len (t)], v) +
+
+ Enhance core table.insert to return its result. + If pos is not given, respect __len metamethod when calculating + default append. Also, diagnose out of bounds pos arguments + consistently on any supported version of Lua. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
  • pos + int + index at which to insert new element + (default len (t)) +
  • +
  • v + value to insert into t +
  • +
+ +

Returns:

+
    + + table + t +
+ + + +

Usage:

+
    +
    + --> {1, "x", 2, 3, "y"}
    + insert (insert ({1, 2, 3}, 2, "x"), "y")
    +
+ +
+
+ + invert (t) +
+
+ Invert a table. + + +

Parameters:

+
    +
  • t + table + a table with {k=v, ...} +
  • +
+ +

Returns:

+
    + + table + inverted table {v=k, ...} +
+ + + +

Usage:

+
    +
    + --> {a=1, b=2, c=3}
    + invert {"a", "b", "c"}
    +
+ +
+
+ + keys (t) +
+
+ Make the list of keys in table. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    + + table + list of keys from t +
+ + +

See also:

+ + +

Usage:

+
    +
    globals = keys (_G)
    +
+ +
+
+ + len (t) +
+
+ Equivalent to # operation, but respecting __len even on Lua 5.1. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    + + int + length of list part of t +
+ + + +

Usage:

+
    +
    for i = 1, len (t) do process (t[i]) end
    +
+ +
+
+ + maxn (t) +
+
+ Largest integer key in a table. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    + + int + largest integer key in t +
+ + + +

Usage:

+
    +
    + --> 42
    + maxn {"a", b="c", 99, [42]="x", "x", [5]=67}
    +
+ +
+
+ + merge (t, u[, map={}[, nometa]]) +
+
+ Destructively merge another table's fields into another. + + +

Parameters:

+
    +
  • t + table + destination table +
  • +
  • u + table + table with fields to merge +
  • +
  • map + table + table of {old_key=new_key, ...} + (default {}) +
  • +
  • nometa + bool + if true or ":nometa" don't copy metatable + (optional) +
  • +
+ +

Returns:

+
    + + table + t with fields from u merged in +
+ + +

See also:

+ + +

Usage:

+
    +
    merge (_G, require "std.debug", {say = "log"}, ":nometa")
    +
+ +
+
+ + merge_select (t, u[, keys={}[, nometa]]) +
+
+ Destructively merge another table's named fields into table.

+ +

Like merge, but does not merge any fields by default. + + +

Parameters:

+
    +
  • t + table + destination table +
  • +
  • u + table + table with fields to merge +
  • +
  • keys + table + list of keys to copy + (default {}) +
  • +
  • nometa + bool + if true or ":nometa" don't copy metatable + (optional) +
  • +
+ +

Returns:

+
    + + table + copy of fields in selection from t, also sharing t's + metatable unless nometa +
+ + +

See also:

+ + +

Usage:

+
    +
    merge_select (_G, require "std.debug", {"say"}, false)
    +
+ +
+
+ + monkey_patch ([namespace=_G]) +
+
+ Overwrite core table methods with std enhanced versions. + + +

Parameters:

+
    +
  • namespace + table + where to install global functions + (default _G) +
  • +
+ +

Returns:

+
    + + table + the module table +
+ + + +

Usage:

+
    +
    local table = require "std.table".monkey_patch ()
    +
+ +
+
+ + new ([x=nil[, t={}]]) +
+
+ Make a table with a default value for unset keys. + + +

Parameters:

+
    +
  • x + default entry value + (default nil) +
  • +
  • t + table + initial table + (default {}) +
  • +
+ +

Returns:

+
    + + table + table whose unset elements are x +
+ + + +

Usage:

+
    +
    t = new (0)
    +
+ +
+
+ + okeys (t) +
+
+ Make an ordered list of keys in table. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
+ +

Returns:

+
    + + table + ordered list of keys from t +
+ + +

See also:

+ + +

Usage:

+
    +
    globals = keys (_G)
    +
+ +
+
+ + pack (...) +
+
+ Turn a tuple into a list. + + +

Parameters:

+
    +
  • ... + tuple +
  • +
+ +

Returns:

+
    + + list +
+ + + +

Usage:

+
    +
    + --> {1, 2, "ax"}
    + pack (("ax1"):find "(%D+)")
    +
+ +
+
+ + project (fkey, tt) +
+
+ Project a list of fields from a list of tables. + + +

Parameters:

+
    +
  • fkey + field to project +
  • +
  • tt + table + a list of tables +
  • +
+ +

Returns:

+
    + + table + list of fkey fields from tt +
+ + + +

Usage:

+
    +
    + --> {1, 3, "yy"}
    + project ("xx", {{"a", xx=1, yy="z"}, {"b", yy=2}, {"c", xx=3}, {xx="yy"})
    +
+ +
+
+ + remove (t[, pos=len (t)]) +
+
+ Enhance core table.remove to respect __len when pos is omitted. + Also, diagnose out of bounds pos arguments consistently on any supported + version of Lua. + + +

Parameters:

+
    +
  • t + table + a table +
  • +
  • pos + int + index from which to remove an element + (default len (t)) +
  • +
+ +

Returns:

+
    + + removed value, or else nil +
+ + + +

Usage:

+
    +
    + --> {1, 2, 5}
    + t = {1, 2, "x", 5}
    + remove (t, 3) == "x" and t
    +
+ +
+
+ + shape (dims, t) +
+
+ Shape a table according to a list of dimensions.

+ +

Dimensions are given outermost first and items from the original + list are distributed breadth first; there may be one 0 indicating + an indefinite number. Hence, {0} is a flat list, + {1} is a singleton, {2, 0} is a list of + two lists, and {0, 2} is a list of pairs.

+ +

Algorithm: turn shape into all positive numbers, calculating + the zero if necessary and making sure there is at most one; + recursively walk the shape, adding empty tables until the bottom + level is reached at which point add table items instead, using a + counter to walk the flattened original list. + + +

Parameters:

+
    +
  • dims + table + table of dimensions {d1, ..., dn} +
  • +
  • t + table + a table of elements +
  • +
+ +

Returns:

+
    + + reshaped list +
+ + + +

Usage:

+
    +
    + --> {{"a", "b"}, {"c", "d"}, {"e", "f"}}
    + shape ({3, 2}, {"a", "b", "c", "d", "e", "f"})
    +
+ +
+
+ + size (t) +
+
+ Find the number of elements in a table. + + +

Parameters:

+
    +
  • t + table + any table +
  • +
+ +

Returns:

+
    + + int + number of non-nil values in t +
+ + + +

Usage:

+
    +
    + --> 3
    + size {foo = true, bar = true, baz = false}
    +
+ +
+
+ + sort (t[, c=std.operator.lt]) +
+
+ Enhance core table.sort to return its result. + + +

Parameters:

+
    +
  • t + table + unsorted table +
  • +
  • c + comparator + ordering function callback + (default std.operator.lt) +
  • +
+ +

Returns:

+
    + + t with keys sorted accordind to c +
+ + + +

Usage:

+
    +
    table.concat (sort (object))
    +
+ +
+
+ + unpack (t[, i=1[, j=table.maxn(t)]]) +
+
+ Enhance core table.unpack to always unpack up to maxn (t). + + +

Parameters:

+
    +
  • t + table + table to act on +
  • +
  • i + int + first index to unpack + (default 1) +
  • +
  • j + int + last index to unpack + (default table.maxn(t)) +
  • +
+ +

Returns:

+
    + + ... values of numeric indices of t +
+ + + +

Usage:

+
    +
    return unpack (results_table)
    +
+ +
+
+ + values (t) +
+
+ Make the list of values of a table. + + +

Parameters:

+
    +
  • t + table + any table +
  • +
+ +

Returns:

+
    + + table + list of values in t +
+ + +

See also:

+ + +

Usage:

+
    +
    + --> {"a", "c", 42}
    + values {"a", b="c", [-1]=42}
    +
+ +
+
+

Types

+ + +
+
+ + comparator (a, b) +
+
+ Signature of a sort comparator function. + + +

Parameters:

+
    +
  • a + any object +
  • +
  • b + any object +
  • +
+ +

Returns:

+
    + + boolean + true if a sorts before b, otherwise false +
+ + +

See also:

+ + +

Usage:

+
    +
    + local reversor = function (a, b) return a > b end
    + sort (t, reversor)
    +
+ +
+
+ + +
+
+
+generated by LDoc 1.4.3 +Last updated 2018-09-03 17:48:42 +
+
+ + diff --git a/spec/debug_spec.yaml b/spec/debug_spec.yaml deleted file mode 100644 index 5102723..0000000 --- a/spec/debug_spec.yaml +++ /dev/null @@ -1,222 +0,0 @@ -# General Lua Libraries for Lua 5.1, 5.2 & 5.3 -# Copyright (C) 2011-2018 stdlib authors - -before: | - base_module = 'debug' - this_module = 'std.debug' - global_table = '_G' - - extend_base = {'getfenv', 'setfenv', 'say', 'trace'} - - M = require(this_module) - - -specify std.debug: -- context when required: - - context by name: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by=this_module}). - to_equal {} - - it does not touch the core debug table: - expect(show_apis {added_to=base_module, by=this_module}). - to_equal {} - - it contains apis from the core debug table: - expect(show_apis {from=base_module, not_in=this_module}). - to_contain.a_permutation_of(extend_base) - - - context via the std module: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by='std'}). - to_equal {} - - it does not touch the core debug table: - expect(show_apis {added_to=base_module, by='std'}). - to_equal {} - - -- describe debug: - - it does nothing when std._debug is disabled: - expect(luaproc [[ - require 'std._debug'(false) - require 'std.debug'('nothing to see here') - ]]).not_to_contain_error 'nothing to see here' - - it writes to stderr when std._debug is not set: - expect(luaproc [[ - require 'std.debug'('debugging') - ]]).to_contain_error 'debugging' - - it writes to stderr when std._debug is enabled: - expect(luaproc [[ - require 'std._debug'(true) - require 'std.debug'('debugging') - ]]).to_contain_error 'debugging' - - it writes to stderr when std._debug.level is not set: - expect(luaproc [[ - require 'std._debug'() - require 'std.debug'('debugging') - ]]).to_contain_error 'debugging' - - it writes to stderr when std._debug.level is specified: - expect(luaproc [[ - require 'std._debug'.level = 0 - require 'std.debug'('debugging') - ]]).to_contain_error 'debugging' - expect(luaproc [[ - require 'std._debug'.level = 1 - require 'std.debug'('debugging') - ]]).to_contain_error 'debugging' - expect(luaproc [[ - require 'std._debug'.level = 2 - require 'std.debug'('debugging') - ]]).to_contain_error 'debugging' - - -- describe say: - - it uses normalize.str: - expect(luaproc [[require 'std.debug'.say {'debugging'}]]). - to_contain_error(require 'std.normalize'.str {'debugging'}) - - context when std._debug is disabled: - - before: - preamble = [[ - require 'std._debug'(false) - ]] - - it does nothing when message level is not set: - expect(luaproc(preamble .. [[ - require 'std.debug'.say 'nothing to see here' - ]])).not_to_contain_error 'nothing to see here' - - it does nothing when message is set: - for _, level in next, {-999, 0, 1, 2, 999} do - expect(luaproc(preamble .. [[ - require 'std.debug'.say(]] .. level .. [[, 'nothing to see here') - ]])).not_to_contain_error 'nothing to see here' - end - - context when std._debug is not set: - - it writes to stderr when message level is not set: - expect(luaproc [[ - require 'std.debug'.say 'debugging' - ]]).to_contain_error 'debugging' - - it writes to stderr when message level is 1 or lower: - for _, level in next, {-999, 0, 1} do - expect(luaproc([[ - require 'std.debug'.say(]] .. level .. [[, 'debugging') - ]])).to_contain_error 'debugging' - end - - it does nothing when message level is 2 or higher: - for _, level in next, {2, 999} do - expect(luaproc([[ - require 'std.debug'.say(]] .. level .. [[, 'nothing to see here') - ]])).not_to_contain_error 'nothing to see here' - end - - context when std._debug is enabled: - - before: - preamble = [[ - require 'std._debug'(true) - ]] - - it writes to stderr when message level is not set: - expect(luaproc(preamble .. [[ - require 'std.debug'.say 'debugging' - ]])).to_contain_error 'debugging' - - it writes to stderr when message level is 1 or lower: - for _, level in next, {-999, 0, 1} do - expect(luaproc(preamble .. [[ - require 'std.debug'.say(]] .. level .. [[, 'debugging') - ]])).to_contain_error 'debugging' - end - - it does nothing when message level is 2 or higher: - for _, level in next, {2, 999} do - expect(luaproc(preamble .. [[ - require 'std.debug'.say(]] .. level .. [[, 'nothing to see here') - ]])).not_to_contain_error 'nothing to see here' - end - - context when std._debug.level is not set: - - it writes to stderr when message level is not set: - expect(luaproc [[ - require 'std.debug'.say 'debugging' - ]]).to_contain_error 'debugging' - - it writes to stderr when message level is 1 or lower: - for _, level in next, {-999, 0, 1} do - expect(luaproc([[ - require 'std.debug'.say(]] .. level .. [[, 'debugging') - ]])).to_contain_error 'debugging' - end - - it does nothing when message level is 2 or higher: - for _, level in next, {2, 999} do - expect(luaproc([[ - require 'std.debug'.say(]] .. level .. [[, 'nothing to see here') - ]])).not_to_contain_error 'nothing to see here' - end - - context when std._debug.level is specified: - - it writes to stderr when message level is 1 or lower: - for _, level in next, {0, 1, 2} do - expect(luaproc([[ - require 'std._debug'.level = ]] .. level .. [[ - require 'std.debug'.say 'debugging' - ]])).to_contain_error 'debugging' - end - - it does nothing when message level is higher than debug level: - expect(luaproc [[ - require 'std._debug'.level = 2 - require 'std.debug'.say(3, 'nothing to see here') - ]]).not_to_contain_error 'nothing to see here' - - it writes to stderr when message level equals debug level: - expect(luaproc [[ - require 'std._debug'.level = 2 - require 'std.debug'.say(2, 'debugging') - ]]).to_contain_error 'debugging' - - it writes to stderr when message level is lower than debug level: - expect(luaproc [[ - require 'std._debug'.level = 2 - require 'std.debug'.say(1, 'debugging') - ]]).to_contain_error 'debugging' - - -- describe trace: - - before: - f = init(M, this_module, 'trace') - - - it does nothing when debug hint is disabled: - expect(luaproc [[ - require 'std._debug'(false) - require 'std.debug' - os.exit(0) - ]]).to_succeed_with '' - - it does nothing when debug hint is not set: - expect(luaproc [[ - require 'std.debug' - os.exit(0) - ]]).to_succeed_with '' - - it does nothing when debug hint is enabled: - expect(luaproc [[ - require 'std._debug'(true) - require 'std.debug' - os.exit(0) - ]]).to_succeed_with '' - - it enables automatically when std._debug.call is set: | - expect(luaproc [[ - require 'std._debug'.call = true - require 'std.debug' - os.exit(1) - ]]).to_fail_while_containing ':3 call exit' - - it is enabled manually with debug.sethook: | - expect(luaproc [[ - local debug = require 'std.debug' - debug.sethook(debug.trace, 'cr') - os.exit(1) - ]]).to_fail_while_containing ':3 call exit' - - it writes call trace log to standard error: | - expect(luaproc [[ - local debug = require 'std.debug' - debug.sethook(debug.trace, 'cr') - os.exit(0) - ]]).to_contain_error ':3 call exit' - - it traces lua calls: | - expect(luaproc [[ - local debug = require 'std.debug' -- line 1 - local function incr(i) return i + 1 end -- line 2 - debug.sethook(debug.trace, 'cr') -- line 3 - os.exit(incr(41)) -- line 4 - ]]).to_fail_while_matching '.*:4 call incr <2:.*:4 return incr <2:.*' - - it traces C api calls: | - expect(luaproc [[ - local debug = require 'std.debug' - local function incr(i) return i + 1 end - debug.sethook(debug.trace, 'cr') - os.exit(incr(41)) - ]]).to_fail_while_matching '.*:4 call exit %[C%]%s$' diff --git a/spec/io_spec.yaml b/spec/io_spec.yaml deleted file mode 100644 index 67b850f..0000000 --- a/spec/io_spec.yaml +++ /dev/null @@ -1,439 +0,0 @@ -# General Lua Libraries for Lua 5.1, 5.2 & 5.3 -# Copyright (C) 2011-2018 stdlib authors - -before: | - base_module = 'io' - this_module = 'std.io' - global_table = '_G' - - extend_base = {'catdir', 'catfile', 'die', 'dirname', - 'process_files', 'readlines', 'shell', 'slurp', - 'splitdir', 'warn', 'writelines'} - - dirsep = string.match(package.config, '^([^\n]+)\n') - - M = require(this_module) - - -specify std.io: -- context when required: - - context by name: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by=this_module}). - to_equal {} - - it does not touch the core io table: - expect(show_apis {added_to=base_module, by=this_module}). - to_equal {} - - it contains apis from the core io table: - expect(show_apis {from=base_module, not_in=this_module}). - to_contain.a_permutation_of(extend_base) - - - context via the std module: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by='std'}). - to_equal {} - - it does not touch the core io table: - expect(show_apis {added_to=base_module, by='std'}). - to_equal {} - - -- describe catdir: - - before: | - f = M.catdir - - - context with bad arguments: - badargs.diagnose(f, 'std.io.catdir(string*)') - - - it treats initial empty string as root directory: - expect(f('')).to_be(dirsep) - expect(f('', '')).to_be(dirsep) - expect(f('', 'root')).to_be(dirsep .. 'root') - - it returns a single argument unchanged: - expect(f('hello')).to_be 'hello' - - it joins multiple arguments with platform directory separator: - expect(f('one', 'two')).to_be('one' .. dirsep .. 'two') - expect(f('1', '2', '3', '4', '5')). - to_be(table.concat({'1', '2', '3', '4', '5'}, dirsep)) - - -- describe catfile: - - before: - f = M.catfile - - - context with bad arguments: - badargs.diagnose(f, 'std.io.catfile(string*)') - - - it treats initial empty string as root directory: - expect(f('', '')).to_be(dirsep) - expect(f('', 'root')).to_be(dirsep .. 'root') - - it returns a single argument unchanged: - expect(f('')).to_be '' - expect(f('hello')).to_be 'hello' - - it joins multiple arguments with platform directory separator: - expect(f('one', 'two')).to_be('one' .. dirsep .. 'two') - expect(f('1', '2', '3', '4', '5')). - to_be(table.concat({'1', '2', '3', '4', '5'}, dirsep)) - - -- describe die: - - before: | - script = [[require 'std.io'.die "By 'eck!"]] - - f = M.die - - - context with bad arguments: - badargs.diagnose(f, 'std.io.die(string, ?any*)') - - - it outputs a message to stderr: | - expect(luaproc(script)).to_fail_while_matching ": By 'eck!\n" - - it ignores `prog.line` without `prog.file` or `prog.name`: | - script = [[prog = {line=125};]] .. script - expect(luaproc(script)).to_fail_while_matching ": By 'eck!\n" - - it ignores `opts.line` without `opts.program`: | - script = [[opts = {line=99};]] .. script - expect(luaproc(script)).to_fail_while_matching ": By 'eck!\n" - - it prefixes `prog.name` if any: | - script = [[prog = {name='name'};]] .. script - expect(luaproc(script)).to_fail_while_matching ": name: By 'eck!\n" - - it appends `prog.line` if any, to `prog.name`: | - script = [[prog = {line=125, name='name'};]] .. script - expect(luaproc(script)).to_fail_while_matching ": name:125: By 'eck!\n" - - it prefixes `prog.file` if any: | - script = [[prog = {file='file'};]] .. script - expect(luaproc(script)).to_fail_while_matching ": file: By 'eck!\n" - - it appends `prog.line` if any, to `prog.name`: | - script = [[prog = {file='file', line=125};]] .. script - expect(luaproc(script)).to_fail_while_matching ": file:125: By 'eck!\n" - - it prefers `prog.name` to `prog.file` or `opts.program`: | - script = [[ - prog = {file='file', name='name'} - opts = {program='program'} - ]] .. script - expect(luaproc(script)).to_fail_while_matching ": name: By 'eck!\n" - - it appends `prog.line` if any to `prog.name` over anything else: | - script = [[ - prog = {file='file', line=125, name='name'} - opts = {line=99, program='program'} - ]] .. script - expect(luaproc(script)).to_fail_while_matching ": name:125: By 'eck!\n" - - it prefers `prog.file` to `opts.program`: | - script = [[ - prog = {file='file'}; opts = {program='program'} - ]] .. script - expect(luaproc(script)).to_fail_while_matching ": file: By 'eck!\n" - - it appends `prog.line` if any to `prog.file` over using `opts`: | - script = [[ - prog = {file='file', line=125} - opts = {line=99, program='program'} - ]] .. script - expect(luaproc(script)).to_fail_while_matching ": file:125: By 'eck!\n" - - it prefixes `opts.program` if any: | - script = [[opts = {program='program'};]] .. script - expect(luaproc(script)).to_fail_while_matching ": program: By 'eck!\n" - - it appends `opts.line` if any, to `opts.program`: | - script = [[opts = {line=99, program='program'};]] .. script - expect(luaproc(script)).to_fail_while_matching ": program:99: By 'eck!\n" - - -- describe dirname: - - before: - f = M.dirname - path = table.concat({'', 'one', 'two', 'three'}, dirsep) - - - context with bad arguments: - badargs.diagnose(f, 'std.io.dirname(string)') - - - it removes final separator and following: - expect(f(path)).to_be(table.concat({'', 'one', 'two'}, dirsep)) - - -- describe process_files: - - before: - name = 'Makefile' - names = {'LICENSE.md', 'Makefile', 'README.md'} - ascript = [[ - require 'std.io'.process_files(function(a) - print(a) - end) - ]] - lscript = [[ - require 'std.io'.process_files('=print(_1)') - ]] - iscript = [[ - require 'std.io'.process_files(function(_, i) - print(i) - end) - ]] - catscript = [[ - require 'std.io'.process_files(function() - io.write(io.input():read '*a') - end) - ]] - - f = M.process_files - - - context with bad arguments: | - badargs.diagnose(f, 'std.io.process_files(func)') - - examples { - ["it diagnoses non-file 'arg' elements"] = function() - expect(luaproc(ascript, 'not-an-existing-file')).to_contain_error.any_of { - "cannot open file 'not-an-existing-file'", -- Lua 5.2 - "bad argument #1 to 'input' (not-an-existing-file:", -- Lua 5.1 - } - end - } - - - it defaults to `-` if no arguments were passed: - expect(luaproc(ascript)).to_output '-\n' - - it iterates over arguments with supplied function: - expect(luaproc(ascript, name)).to_output(name .. '\n') - expect(luaproc(ascript, names)). - to_output(table.concat(names, '\n') .. '\n') - - it passes argument numbers to supplied function: - expect(luaproc(iscript, names)).to_output '1\n2\n3\n' - - it sets each file argument as the default input: - expect(luaproc(catscript, name)).to_output(concat_file_content(name)) - expect(luaproc(catscript, names)). - to_output(concat_file_content(unpack(names))) - - it processes io.stdin if no arguments were passed: - ## FIXME: where does that closing newline come from?? - expect(luaproc(catscript, nil, 'some\nlines\nof input')).to_output 'some\nlines\nof input\n' - - it processes io.stdin for `-` argument: - ## FIXME: where does that closing newline come from?? - expect(luaproc(catscript, '-', 'some\nlines\nof input')).to_output 'some\nlines\nof input\n' - - -- describe readlines: - - before: | - name = 'Makefile' - h = io.open(name) - lines = {} - for l in h:lines() do - lines[#lines + 1] = l - end - h:close() - - defaultin = io.input() - - f, badarg = init(M, this_module, 'readlines') - - after: - if io.type(defaultin) ~= 'closed file' then - io.input(defaultin) - end - - - context with bad arguments: | - badargs.diagnose(f, 'std.io.readlines(?file|string)') - - if have_typecheck then - examples { - ['it diagnoses non-existent file'] = function() - expect(f 'not-an-existing-file'). - to_raise "bad argument #1 to 'std.io.readlines'(" -- system dependent error message - end - } - closed = io.open(name, 'r') closed:close() - examples { - ['it diagnoses closed file argument'] = function() - expect(f(closed)).to_raise(badarg(1, '?file|string', 'closed file')) - end - } - end - - - it closes file handle upon completion: - h = io.open(name) - expect(io.type(h)).not_to_be 'closed file' - f(h) - expect(io.type(h)).to_be 'closed file' - - it reads lines from an existing named file: - expect(f(name)).to_equal(lines) - - it reads lines from an open file handle: - expect(f(io.open(name))).to_equal(lines) - - it reads from default input stream with no arguments: - io.input(name) - expect(f()).to_equal(lines) - - -- describe shell: - - before: - f = M.shell - - - context with bad arguments: - badargs.diagnose(f, 'std.io.shell(string)') - - - it returns the output from a shell command string: - expect(f [[printf '%s\n' 'foo' 'bar']]).to_be 'foo\nbar\n' - - -- describe slurp: - - before: | - name = 'Makefile' - h = io.open(name) - content = h:read '*a' - h:close() - - defaultin = io.input() - f, badarg = init(M, this_module, 'slurp') - - after: - if io.type(defaultin) ~= 'closed file' then - io.input(defaultin) - end - - - context with bad arguments: | - badargs.diagnose(f, 'std.io.slurp(?file|string)') - - if have_typecheck then - examples { - ['it diagnoses non-existent file'] = function() - expect(f 'not-an-existing-file'). - to_raise "bad argument #1 to 'std.io.slurp'(" -- system dependent error message - end - } - closed = io.open(name, 'r') closed:close() - examples { - ['it diagnoses closed file argument'] = function() - expect(f(closed)).to_raise(badarg(1, '?file|string', 'closed file')) - end - } - end - - - it reads content from an existing named file: - expect(f(name)).to_be(content) - - it reads content from an open file handle: - expect(f(io.open(name))).to_be(content) - - it closes file handle upon completion: - h = io.open(name) - expect(io.type(h)).not_to_be 'closed file' - f(h) - expect(io.type(h)).to_be 'closed file' - - it reads from default input stream with no arguments: - io.input(name) - expect(f()).to_be(content) - - -- describe splitdir: - - before: - f = M.splitdir - - - context with bad arguments: - badargs.diagnose(f, 'std.io.splitdir(string)') - - - it returns a filename as a one element list: - expect(f('hello')).to_equal {'hello'} - - it splits root directory in two empty elements: - expect(f(dirsep)).to_equal {'', ''} - - it returns initial empty string for absolute path: - expect(f(dirsep .. 'root')).to_equal {'', 'root'} - - it returns multiple components split at platform directory separator: - expect(f('one' .. dirsep .. 'two')).to_equal {'one', 'two'} - expect(f(table.concat({'1', '2', '3', '4', '5'}, dirsep))). - to_equal {'1', '2', '3', '4', '5'} - - -- describe warn: - - before: - script = [[require 'std.io'.warn 'Ayup!']] - f = M.warn - - - context with bad arguments: - badargs.diagnose(f, 'std.io.warn(string, ?any*)') - - - it outputs a message to stderr: - expect(luaproc(script)).to_output_error 'Ayup!\n' - - it ignores `prog.line` without `prog.file`, `prog.name` or `opts.program`: - script = [[prog = {line=125};]] .. script - expect(luaproc(script)).to_output_error 'Ayup!\n' - - it prefixes `prog.name` if any: | - script = [[prog = {name='name'};]] .. script - expect(luaproc(script)).to_output_error 'name: Ayup!\n' - - it appends `prog.line` if any, to `prog.name`: | - script = [[prog = {line=125, name='name'};]] .. script - expect(luaproc(script)).to_output_error 'name:125: Ayup!\n' - - it prefixes `prog.file` if any: | - script = [[prog = {file='file'};]] .. script - expect(luaproc(script)).to_output_error 'file: Ayup!\n' - - it appends `prog.line` if any, to `prog.name`: | - script = [[prog = {file='file', line=125};]] .. script - expect(luaproc(script)).to_output_error 'file:125: Ayup!\n' - - it prefers `prog.name` to `prog.file` or `opts.program`: | - script = [[ - prog = {file='file', name='name'} - opts = {program='program'} - ]] .. script - expect(luaproc(script)).to_output_error 'name: Ayup!\n' - - it appends `prog.line` if any to `prog.name` over anything else: | - script = [[ - prog = {file='file', line=125, name='name'} - opts = {line=99, program='program'} - ]] .. script - expect(luaproc(script)).to_output_error 'name:125: Ayup!\n' - - it prefers `prog.file` to `opts.program`: | - script = [[ - prog = {file='file'}; opts = {program='program'} - ]] .. script - expect(luaproc(script)).to_output_error 'file: Ayup!\n' - - it appends `prog.line` if any to `prog.file` over using `opts`: | - script = [[ - prog = {file='file', line=125} - opts = {line=99, program='program'} - ]] .. script - expect(luaproc(script)).to_output_error 'file:125: Ayup!\n' - - it prefixes `opts.program` if any: | - script = [[opts = {program='program'};]] .. script - expect(luaproc(script)).to_output_error 'program: Ayup!\n' - - it appends `opts.line` if any, to `opts.program`: | - script = [[opts = {line=99, program='program'};]] .. script - expect(luaproc(script)).to_output_error 'program:99: Ayup!\n' - - -- describe writelines: - - before: | - name = os.tmpname() - h = io.open(name, 'w') - lines = M.readlines(io.open 'Makefile') - - defaultout = io.output() - f, badarg = init(M, this_module, 'writelines') - - after: - if io.type(defaultout) ~= 'closed file' then - io.output(defaultout) - end - h:close() - os.remove(name) - - - context with bad arguments: - - 'it diagnoses argument #1 type not FILE*, string, number or nil': - if have_typecheck then - expect(f(false)).to_raise(badarg(1, '?file|string|number', 'boolean')) - end - - 'it diagnoses argument #2 type not string, number or nil': - if have_typecheck then - expect(f(1, false)).to_raise(badarg(2, 'string|number', 'boolean')) - end - - 'it diagnoses argument #3 type not string, number or nil': - if have_typecheck then - expect(f(1, 2, false)).to_raise(badarg(3, 'string|number', 'boolean')) - end - - it diagnoses closed file argument: | - closed = io.open(name, 'r') closed:close() - if have_typecheck then - expect(f(closed)).to_raise(badarg(1, '?file|string|number', 'closed file')) - end - - - it does not close the file handle upon completion: - expect(io.type(h)).not_to_be 'closed file' - f(h, 'foo') - expect(io.type(h)).not_to_be 'closed file' - - it writes lines to an open file handle: - f(h, unpack(lines)) - h:flush() - expect(M.readlines(io.open(name))).to_equal(lines) - - it accepts number valued arguments: - f(h, 1, 2, 3) - h:flush() - expect(M.readlines(io.open(name))).to_equal {'1', '2', '3'} - - it writes to default output stream with non-file first argument: - io.output(h) - f(unpack(lines)) - h:flush() - expect(M.readlines(io.open(name))).to_equal(lines) diff --git a/spec/math_spec.yaml b/spec/math_spec.yaml deleted file mode 100644 index ed08753..0000000 --- a/spec/math_spec.yaml +++ /dev/null @@ -1,99 +0,0 @@ -# General Lua Libraries for Lua 5.1, 5.2 & 5.3 -# Copyright (C) 2011-2018 stdlib authors - -before: - base_module = 'math' - this_module = 'std.math' - global_table = '_G' - - extend_base = {'floor', 'round'} - - M = require(this_module) - - -specify std.math: -- context when required: - - context by name: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by=this_module}). - to_equal {} - - it does not touch the core math table: - expect(show_apis {added_to=base_module, by=this_module}). - to_equal {} - - it contains apis from the core math table: - expect(show_apis {from=base_module, not_in=this_module}). - to_contain.a_permutation_of(extend_base) - - - context via the std module: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by='std'}). - to_equal {} - - it does not touch the core math table: - expect(show_apis {added_to=base_module, by='std'}). - to_equal {} - - -- describe floor: - - before: - f = M.floor - - - context with bad arguments: - badargs.diagnose(f, 'std.math.floor(number, ?int)') - - - it rounds to the nearest smaller integer: - expect(f(1.2)).to_be(1) - expect(f(1.9)).to_be(1) - expect(f(999e-2)).to_be(9) - expect(f(999e-3)).to_be(0) - - it rounds down to specified number of decimal places: - expect(f(1.2345, 0)).to_be(1.0) - expect(f(1.2345, 1)).to_be(1.2) - expect(f(1.2345, 2)).to_be(1.23) - expect(f(9.9999, 2)).to_be(9.99) - expect(f(99999e-3, 3)).to_be(99999e-3) - expect(f(99999e-4, 3)).to_be(9999e-3) - expect(f(99999e-5, 3)).to_be(999e-3) - - -- describe round: - - before: - f = M.round - - - context with bad arguments: - badargs.diagnose(f, 'std.math.round(number, ?int)') - - - it rounds to the nearest integer: - expect(f(1.2)).to_be(1) - expect(f(1.9)).to_be(2) - expect(f(949e-2)).to_be(9) - expect(f(999e-2)).to_be(10) - - it rounds to specified number of decimal places: - expect(f(1.234, 0)).to_be(1.0) - expect(f(5.678, 0)).to_be(6.0) - expect(f(1.234, 1)).to_be(1.2) - expect(f(5.678, 1)).to_be(5.7) - expect(f(1.234, 2)).to_be(1.23) - expect(f(5.678, 2)).to_be(5.68) - expect(f(9.999, 2)).to_be(10) - expect(f(11111e-2, 3)).to_be(11111e-2) - expect(f(99999e-2, 3)).to_be(99999e-2) - expect(f(11111e-3, 3)).to_be(11111e-3) - expect(f(99999e-3, 3)).to_be(99999e-3) - expect(f(11111e-4, 3)).to_be(1111e-3) - expect(f(99999e-4, 3)).to_be(10) - expect(f(99999e-5, 3)).to_be(1) - - it rounds negative values correctly: - expect(f(-1.234, 0)).to_be(-1.0) - expect(f(-5.678, 0)).to_be(-6.0) - expect(f(-1.234, 1)).to_be(-1.2) - expect(f(-5.678, 1)).to_be(-5.7) - expect(f(-1.234, 2)).to_be(-1.23) - expect(f(-5.678, 2)).to_be(-5.68) - expect(f(-9.999, 2)).to_be(-10) - expect(f(-11111e-2, 3)).to_be(-11111e-2) - expect(f(-99999e-2, 3)).to_be(-99999e-2) - expect(f(-11111e-3, 3)).to_be(-11111e-3) - expect(f(-99999e-3, 3)).to_be(-99999e-3) - expect(f(-11111e-4, 3)).to_be(-1111e-3) - expect(f(-99999e-4, 3)).to_be(-10) - expect(f(-99999e-5, 3)).to_be(-1) diff --git a/spec/package_spec.yaml b/spec/package_spec.yaml deleted file mode 100644 index 23ce961..0000000 --- a/spec/package_spec.yaml +++ /dev/null @@ -1,202 +0,0 @@ -# General Lua Libraries for Lua 5.1, 5.2 & 5.3 -# Copyright (C) 2011-2018 stdlib authors - -before: | - base_module = 'package' - this_module = 'std.package' - global_table = '_G' - - extend_base = {'find', 'insert', 'mappath', 'normalize', 'remove'} - - M = require(this_module) - - path = M.normalize('begin', 'middle', 'end') - - function catfile(...) - return table.concat({...}, M.dirsep) - end - function catpath(...) - return table.concat({...}, M.pathsep) - end - - -specify std.package: -- context when required: - - context by name: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by=this_module}). - to_equal {} - - it does not touch the core package table: - expect(show_apis {added_to=base_module, by=this_module}). - to_equal {} - - it contains apis from the core package table: - expect(show_apis {from=base_module, not_in=this_module}). - to_contain.a_permutation_of(extend_base) - - - context via the std module: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by='std'}). - to_equal {} - - it does not touch the core package table: - expect(show_apis {added_to=base_module, by='std'}). - to_equal {} - - -- describe find: - - before: | - path = table.concat({'begin', 'm%ddl.', 'end'}, M.pathsep) - - f = M.find - - - context with bad arguments: - badargs.diagnose(f, 'std.package.find(string, string, ?int, ?boolean|:plain)') - - - it returns nil for unmatched element: - expect(f(path, 'unmatchable')).to_be(nil) - - it returns the element index for a matched element: - expect(f(path, 'end')).to_be(3) - - it returns the element text for a matched element: - i, element = f(path, 'e.*n') - expect({i, element}).to_equal {1, 'begin'} - - it accepts a search start element argument: - i, element = f(path, 'e.*n', 2) - expect({i, element}).to_equal {3, 'end'} - - it works with plain text search strings: - expect(f(path, 'm%ddl.')).to_be(nil) - i, element = f(path, '%ddl.', 1, ':plain') - expect({i, element}).to_equal {2, 'm%ddl.'} - - -- describe insert: - - before: - f = M.insert - - - context with bad arguments: - badargs.diagnose(f, 'std.package.insert(string, [int], string)') - - - it appends by default: - expect(f(path, 'new')). - to_be(M.normalize('begin', 'middle', 'end', 'new')) - - it prepends with pos set to 1: - expect(f(path, 1, 'new')). - to_be(M.normalize('new', 'begin', 'middle', 'end')) - - it can insert in the middle too: - expect(f(path, 2, 'new')). - to_be(M.normalize('begin', 'new', 'middle', 'end')) - expect(f(path, 3, 'new')). - to_be(M.normalize('begin', 'middle', 'new', 'end')) - - it normalizes the returned path: - path = table.concat({'begin', 'middle', 'end'}, M.pathsep) - expect(f(path, 'new')). - to_be(M.normalize('begin', 'middle', 'end', 'new')) - expect(f(path, 1, './x/../end')). - to_be(M.normalize('end', 'begin', 'middle')) - - -- describe mappath: - - before: | - expected = require 'std.string'.split(path, M.pathsep) - - f = M.mappath - - - context with bad arguments: - badargs.diagnose(f, 'std.package.mappath(string, function, ?any*)') - - - it calls a function with each path element: - t = {} - f(path, function(e) - t[#t + 1] = e - end) - expect(t).to_equal(expected) - - it passes additional arguments through: | - reversed = {} - for i = #expected, 1, -1 do - table.insert(reversed, expected[i]) - end - t = {} - f(path, function(e, pos) - table.insert(t, pos, e) - end, 1) - expect(t).to_equal(reversed) - - -- describe normalize: - - before: - f = M.normalize - - - context with bad arguments: - badargs.diagnose(f, 'std.package.normalize(string*)') - - - context with a single element: - - it strips redundant . directories: - expect(f './x/./y/.').to_be(catfile('.', 'x', 'y')) - - it strips redundant .. directories: - expect(f '../x/../y/z/..').to_be(catfile('..', 'y')) - expect(f '../x/../y/z/..').to_be(catfile('..', 'y')) - expect(f '../../x/../y/z/..').to_be(catfile('..', '..', 'y')) - expect(f '../../x/../y/./..').to_be(catfile('..', '..')) - expect(f '../../w/x/../../y/z/..').to_be(catfile('..', '..', 'y')) - expect(f '../../w/./../.././z/..').to_be(catfile('..', '..', '..')) - - it leaves leading .. directories unmolested: - expect(f '../../1').to_be(catfile('..', '..', '1')) - expect(f './../../1').to_be(catfile('..', '..', '1')) - - it normalizes / to platform dirsep: - expect(f '/foo/bar').to_be(catfile('', 'foo', 'bar')) - - it normalizes ? to platform pathmark: - expect(f '?.lua'). - to_be(catfile('.', M.pathmark .. '.lua')) - - it strips redundant trailing /: - expect(f '/foo/bar/').to_be(catfile('', 'foo', 'bar')) - - it inserts missing ./ for relative paths: - for _, path in ipairs {'x', './x'} do - expect(f(path)).to_be(catfile('.', 'x')) - end - - context with multiple elements: - - it strips redundant . directories: - expect(f('./x/./y/.', 'x')). - to_be(catpath(catfile('.', 'x', 'y'), catfile('.', 'x'))) - - it strips redundant .. directories: - expect(f('../x/../y/z/..', 'x')). - to_be(catpath(catfile('..', 'y'), catfile('.', 'x'))) - - it normalizes / to platform dirsep: - expect(f('/foo/bar', 'x')). - to_be(catpath(catfile('', 'foo', 'bar'), catfile('.', 'x'))) - - it normalizes ? to platform pathmark: - expect(f('?.lua', 'x')). - to_be(catpath(catfile('.', M.pathmark .. '.lua'), catfile('.', 'x'))) - - it strips redundant trailing /: - expect(f('/foo/bar/', 'x')). - to_be(catpath(catfile('', 'foo', 'bar'), catfile('.', 'x'))) - - it inserts missing ./ for relative paths: - for _, path in ipairs {'x', './x'} do - expect(f(path, 'a')). - to_be(catpath(catfile('.', 'x'), catfile('.', 'a'))) - end - - it eliminates all but the first equivalent elements: - expect(f(catpath('1', 'x', '2', './x', './2', './x/../x'))). - to_be(catpath('./1', './x', './2')) - - -- describe remove: - - before: - f = M.remove - - - context with bad arguments: - badargs.diagnose(f, 'std.package.remove(string, ?int)') - - - it removes the last item by default: - expect(f(path)).to_be(M.normalize('begin', 'middle')) - - it pops the first item with pos set to 1: - expect(f(path, 1)).to_be(M.normalize('middle', 'end')) - - it can remove from the middle too: - expect(f(path, 2)).to_be(M.normalize('begin', 'end')) - - it does not normalize the returned path: - path = table.concat({'begin', 'middle', 'end'}, M.pathsep) - expect(f(path)). - to_be(table.concat({'begin', 'middle'}, M.pathsep)) - - -- it splits package.config up: - expect(string.format('%s\n%s\n%s\n%s\n%s\n', - M.dirsep, M.pathsep, M.pathmark, M.execdir, M.igmark) - ).to_contain(package.config) diff --git a/spec/spec_helper.lua b/spec/spec_helper.lua deleted file mode 100644 index 642712f..0000000 --- a/spec/spec_helper.lua +++ /dev/null @@ -1,416 +0,0 @@ ---[[ - General Lua Libraries for Lua 5.1, 5.2 & 5.3 - Copyright (C) 2011-2018 stdlib authors -]] - -local typecheck -have_typecheck, typecheck = pcall(require, 'typecheck') - -local inprocess = require 'specl.inprocess' -local hell = require 'specl.shell' -local std = require 'specl.std' - -badargs = require 'specl.badargs' - - -local top_srcdir = os.getenv 'top_srcdir' or '.' -local top_builddir = os.getenv 'top_builddir' or '.' - -package.path = std.package.normalize( - top_builddir .. '/lib/?.lua', - top_builddir .. '/lib/?/init.lua', - top_srcdir .. '/lib/?.lua', - top_srcdir .. '/lib/?/init.lua', - package.path -) - - --- Allow user override of LUA binary used by hell.spawn, falling --- back to environment PATH search for 'lua' if nothing else works. -local LUA = os.getenv 'LUA' or 'lua' - - --- Simplified version for specifications, does not support functable --- valued __len metamethod, so don't write examples that need that! -function len(x) - local __len = getmetatable(x) or {} - if type(__len) == 'function' then - return __len(x) - end - if type(x) ~= 'table' then - return #x - end - - local n = #x - for i = 1, n do - if x[i] == nil then - return i -1 - end - end - return n -end - - --- Make sure we have a maxn even when _VERSION ~= 5.1 --- @fixme remove this when we get unpack from specl.std -maxn = table.maxn or function(t) - local n = 0 - for k in pairs(t) do - if type(k) == 'number' and k > n then - n = k - end - end - return n -end - - -pack = table.pack or function(...) - return {n=select('#', ...), ...} -end - - --- Take care to always unpack upto the highest numeric index, for --- consistency across Lua versions. -local _unpack = table.unpack or unpack - --- @fixme pick this up from specl.std with the next release -function unpack(t, i, j) - return _unpack(t, tonumber(i) or 1, tonumber(j or t.n or len(t))) -end - - --- In case we're not using a bleeding edge release of Specl... -_diagnose = badargs.diagnose -badargs.diagnose = function(...) - if have_typecheck then - return _diagnose(...) - end -end - -badargs.result = badargs.result or function(fname, i, want, got) - if want == nil then -- numbers only for narg error - i, want = i - 1, i - end - - if got == nil and type(want) == 'number' then - local s = "bad result #%d from '%s'(no more than %d result%s expected, got %d)" - return s:format(i + 1, fname, i, i == 1 and '' or 's', want) - end - - local function showarg(s) - return('|' .. s .. '|'): - gsub('|%?', '|nil|'): - gsub('|nil|', '|no value|'): - gsub('|any|', '|any value|'): - gsub('|#', '|non-empty '): - gsub('|func|', '|function|'): - gsub('|file|', '|FILE*|'): - gsub('^|', ''): - gsub('|$', ''): - gsub('|([^|]+)$', 'or %1'): - gsub('|', ', ') - end - - return string.format("bad result #%d from '%s'(%s expected, got %s)", - i, fname, showarg(want), got or 'no value') -end - - --- Wrap up badargs function in a succinct single call. -function init(M, mname, fname) - local name =(mname .. '.' .. fname):gsub('^%.', '') - return M[fname], - function(...) - return badargs.format(name, ...) - end, - function(...) - return badargs.result(name, ...) - end -end - - --- A copy of base.lua:type, so that an unloadable base.lua doesn't --- prevent everything else from working. -function objtype(o) - return(getmetatable(o) or {})._type or io.type(o) or type(o) -end - - -function nop() end - - --- Error message specifications use this to shorten argument lists. --- Copied from functional.lua to avoid breaking all tests if functional --- cannot be loaded correctly. -function bind(f, fix) - return function(...) - local arg = {} - for i, v in pairs(fix) do - arg[i] = v - end - local i = 1 - for _, v in pairs {...} do - while arg[i] ~= nil do - i = i + 1 - end - arg[i] = v - end - return f(unpack(arg)) - end -end - - -local function mkscript(code) - local f = os.tmpname() - local h = io.open(f, 'w') - h:write(code) - h:close() - return f -end - - ---- Run some Lua code with the given arguments and input. --- @string code valid Lua code --- @tparam[opt={}] string|table arg single argument, or table of --- arguments for the script invocation. --- @string[opt] stdin standard input contents for the script process --- @treturn specl.shell.Process|nil status of resulting process if --- execution was successful, otherwise nil -function luaproc(code, arg, stdin) - local f = mkscript(code) - if type(arg) ~= 'table' then - arg = {arg} - end - local cmd = {LUA, f, unpack(arg)} - -- inject env and stdin keys separately to avoid truncating `...` in - -- cmd constructor - cmd.env = {LUA_PATH=package.path, LUA_INIT='', LUA_INIT_5_2=''} - cmd.stdin = stdin - local proc = hell.spawn(cmd) - os.remove(f) - return proc -end - - ---- Check deprecation output when calling a named function in the given module. --- Note that the script fragments passed in *argstr* and *objectinit* --- can reference the module table as `M`, and(where it would make sense) --- an object prototype as `P` and instance as `obj`. --- @param deprecate value of `std._debug.deprecate` --- @string module dot delimited module path to load --- @string fname name of a function in the table returned by requiring *module* --- @param[opt=''] args arguments to pass to *fname* call, must be stringifiable --- @string[opt=nil] objectinit object initializer to instantiate an --- object for object method deprecation check --- @treturn specl.shell.Process|nil status of resulting process if --- execution was successful, otherwise nil -function deprecation(deprecate, module, fname, args, objectinit) - args = args or '' - local script - if objectinit == nil then - script = string.format([[ - require 'std._debug'.deprecate = %s - M = require '%s' - P = M.prototype - print(M.%s(%s)) - ]], tostring(deprecate), module, fname, tostring(args)) - else - script = string.format([[ - require 'std._debug'.deprecate = %s - local M = require '%s' - local P = M.prototype - local obj = P(%s) - print(obj:%s(%s)) - ]], tostring(deprecate), module, objectinit, fname, tostring(args)) - end - return luaproc(script) -end - - ---- Concatenate the contents of listed existing files. --- @string ... names of existing files --- @treturn string concatenated contents of those files -function concat_file_content(...) - local t = {} - for _, name in ipairs {...} do - h = io.open(name) - t[#t + 1] = h:read '*a' - end - return table.concat(t) -end - - -local function tabulate_output(code) - local proc = luaproc(code) - if proc.status ~= 0 then - return error(proc.errout) - end - local r = {} - proc.output:gsub('(%S*)[%s]*', - function(x) - if x ~= '' then - r[x] = true - end - end) - return r -end - - ---- Show changes to tables wrought by a require statement. --- There are a few modes to this function, controlled by what named --- arguments are given. Lists new keys in T1 after `require 'import'`: --- --- show_apis {added_to=T1, by=import} --- --- List keys returned from `require 'import'`, which have the same --- value in T1: --- --- show_apis {from=T1, used_by=import} --- --- List keys from `require 'import'`, which are also in T1 but with --- a different value: --- --- show_apis {from=T1, enhanced_by=import} --- --- List keys from T2, which are also in T1 but with a different value: --- --- show_apis {from=T1, enhanced_in=T2} --- --- @tparam table argt one of the combinations above --- @treturn table a list of keys according to criteria above -function show_apis(argt) - local added_to, from, not_in, enhanced_in, enhanced_after, by = - argt.added_to, argt.from, argt.not_in, argt.enhanced_in, - argt.enhanced_after, argt.by - - if added_to and by then - return tabulate_output([[ - local before, after = {}, {} - for k in pairs(]] .. added_to .. [[) do - before[k] = true - end - - local M = require ']] .. by .. [[' - for k in pairs(]] .. added_to .. [[) do - after[k] = true - end - - for k in pairs(after) do - if not before[k] then - print(k) - end - end - ]]) - - elseif from and not_in then - return tabulate_output([[ - local _ENV = require 'std.normalize' { - from = ']] .. from .. [[', - M = require ']] .. not_in .. [[', - } - - for k in pairs(M) do - -- M[1] is typically the module namespace name, don't match - -- that! - if k ~= 1 and from[k] ~= M[k] then - print(k) - end - end - ]]) - - elseif from and enhanced_in then - return tabulate_output([[ - local _ENV = require 'std.normalize' { - from = ']] .. from .. [[', - M = require ']] .. enhanced_in .. [[', - } - - for k, v in pairs(M) do - if from[k] ~= M[k] and from[k] ~= nil then - print(k) - end - end - ]]) - - elseif from and enhanced_after then - return tabulate_output([[ - local _ENV = require 'std.normalize' { - from = ']] .. from .. [[', - } - local before, after = {}, {} - for k, v in pairs(from) do - before[k] = v - end - ]] .. enhanced_after .. [[ - for k, v in pairs(from) do - after[k] = v - end - - for k, v in pairs(before) do - if after[k] ~= nil and after[k] ~= v then - print(k) - end - end - ]]) - end - - assert(false, 'missing argument to show_apis') -end - - --- Stub inprocess.capture if necessary; new in Specl 12. -capture = inprocess.capture or function(f, arg) - return nil, nil, f(unpack(arg or {})) -end - - -do - -- Custom matcher for set size and set membership. - - local util = require 'specl.util' - local matchers = require 'specl.matchers' - - local Matcher, matchers, q = - matchers.Matcher, matchers.matchers, matchers.stringify - - matchers.have_size = Matcher { - function(self, actual, expect) - local size = 0 - for _ in pairs(actual) do - size = size + 1 - end - return size == expect - end, - - actual = 'table', - - format_expect = function(self, expect) - return ' a table containing ' .. expect .. ' elements, ' - end, - - format_any_of = function(self, alternatives) - return ' a table with any of ' .. - util.concat(alternatives, util.QUOTED) .. ' elements, ' - end, - } - - matchers.have_member = Matcher { - function(self, actual, expect) - return actual[expect] ~= nil - end, - - actual = 'set', - - format_expect = function(self, expect) - return ' a set containing ' .. q(expect) .. ', ' - end, - - format_any_of = function(self, alternatives) - return ' a set containing any of ' .. - util.concat(alternatives, util.QUOTED) .. ', ' - end, - } - - -- Alias that doesn't tickle sc_error_message_uppercase. - matchers.raise = matchers.error -end diff --git a/spec/std_spec.yaml b/spec/std_spec.yaml deleted file mode 100644 index b747abf..0000000 --- a/spec/std_spec.yaml +++ /dev/null @@ -1,444 +0,0 @@ -# General Lua Libraries for Lua 5.1, 5.2 & 5.3 -# Copyright (C) 2011-2018 stdlib authors - -before: | - this_module = 'std' - global_table = '_G' - - exported_apis = {'assert', 'elems', 'eval', 'getmetamethod', - 'ielems', 'ipairs', 'npairs', 'pairs', - 'require', 'ripairs', 'rnpairs'} - - -- Tables with iterator metamethods used by various examples. - __pairs = setmetatable({content='a string'}, { - __pairs = function(t) - return function(x, n) - if n < #x.content then - return n+1, string.sub(x.content, n+1, n+1) - end - end, t, 0 - end, - }) - __index = setmetatable({content='a string'}, { - __index = function(t, n) - if n <= #t.content then - return t.content:sub(n, n) - end - end, - __len = function(t) - return #t.content - end, - }) - - M = require(this_module) - M.version = nil -- previous specs may have autoloaded it - - -specify std: -- context when required: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by=this_module}). - to_equal {} - - it exports the documented apis: - t = {} - for k in pairs(M) do - t[#t + 1] = k - end - expect(t).to_contain.a_permutation_of(exported_apis) - -- context when lazy loading: - - it has no submodules on initial load: - for _, v in pairs(M) do - expect(type(v)).not_to_be 'table' - end - - it loads submodules on demand: - lazy = M.math - expect(lazy).to_be(require 'std.math') - - it loads submodule functions on demand: - expect(M.math.round(3.141592)).to_be(3) - -- describe assert: - - before: - f = M.assert - - - context with bad arguments: - badargs.diagnose(f, 'std.assert(?any, ?string, ?any*)') - - - context when it does not trigger: - - it has a truthy initial argument: - expect(f(1)).not_to_raise 'any error' - expect(f(true)).not_to_raise 'any error' - expect(f 'yes').not_to_raise 'any error' - expect(f(false == false)).not_to_raise 'any error' - - it returns the initial argument: - expect(f(1)).to_be(1) - expect(f(true)).to_be(true) - expect(f 'yes').to_be 'yes' - expect(f(false == false)).to_be(true) - - context when it triggers: - - it has a falsey initial argument: - expect(f()).to_raise() - expect(f(false)).to_raise() - expect(f(1 == 0)).to_raise() - - it throws an optional error string: - expect(f(false, 'ah boo')).to_raise 'ah boo' - - it plugs specifiers with string.format: | - expect(f(nil, '%s %d: %q', 'here', 42, 'a string')). - to_raise(string.format('%s %d: %q', 'here', 42, 'a string')) - - -- describe elems: - - before: - f = M.elems - - - context with bad arguments: - badargs.diagnose(f, 'std.elems(table)') - - - it is an iterator over table values: - t = {} - for e in f {'foo', bar='baz', 42} do - t[#t + 1] = e - end - expect(t).to_contain.a_permutation_of {'foo', 'baz', 42} - - it respects __pairs metamethod: | - t = {} - for v in f(__pairs) do - t[#t + 1] = v - end - expect(t). - to_contain.a_permutation_of {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'} - - it works for an empty list: - t = {} - for e in f {} do - t[#t + 1] = e - end - expect(t).to_equal {} - - -- describe eval: - - before: - f = M.eval - - - context with bad arguments: - badargs.diagnose(f, 'std.eval(string)') - - - it diagnoses invalid lua: - # Some internal error when eval tries to call uncompilable '=' code. - expect(f '=').to_raise() - - it evaluates a string of lua code: - expect(f 'math.min(2, 10)').to_be(math.min(2, 10)) - - -- describe getmetamethod: - - before: - f = M.getmetamethod - - - context with bad arguments: - badargs.diagnose(f, 'std.getmetamethod(?any, string)') - - - context with a table: - - before: - method = function() - return 'called' - end - functor = setmetatable({}, {__call=method}) - t = setmetatable({}, { - _type='table', _method=method, _functor=functor, - }) - - it returns nil for missing metamethods: - expect(f(t, 'not a metamethod on t')).to_be(nil) - - it returns nil for non-callable metatable entries: - expect(f(t, '_type')).to_be(nil) - - it returns a method from the metatable: - expect(f(t, '_method')).to_be(method) - expect(f(t, '_method')()).to_be 'called' - - it returns a functor from the metatable: - expect(f(t, '_functor')).to_be(functor) - expect(f(t, '_functor')()).to_be 'called' - - -- describe ielems: - - before: - f = M.ielems - - - context with bad arguments: - badargs.diagnose(f, 'std.ielems(table)') - - - it is an iterator over integer-keyed table values: - t = {} - for e in f {'foo', 42} do - t[#t + 1] = e - end - expect(t).to_equal {'foo', 42} - - it ignores the dictionary part of a table: - t = {} - for e in f {'foo', 42; bar='baz', qux='quux'} do - t[#t + 1] = e - end - expect(t).to_equal {'foo', 42} - - it respects __len metamethod: - t = {} - for v in f(__index) do - t[#t + 1] = v - end - expect(t).to_equal {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'} - - it works for an empty list: - t = {} - for e in f {} do - t[#t + 1] = e - end - expect(t).to_equal {} - - -- describe ipairs: - - before: - f = M.ipairs - - - context with bad arguments: - badargs.diagnose(f, 'std.ipairs(table)') - - - it is an iterator over integer-keyed table values: - t = {} - for i, v in f {'foo', 42} do - t[i] = v - end - expect(t).to_equal {'foo', 42} - - it ignores the dictionary part of a table: - t = {} - for i, v in f {'foo', 42; bar='baz', qux='quux'} do - t[i] = v - end - expect(t).to_equal {'foo', 42} - - it respects __len metamethod: - t = {} - for k, v in f(__index) do - t[k] = v - end - expect(t).to_equal {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'} - - it works for an empty list: - t = {} - for i, v in f {} do - t[i] = v - end - expect(t).to_equal {} - - -- describe npairs: - - before: - f = M.npairs - - - context with bad arguments: - badargs.diagnose(f, 'std.npairs(table)') - - - it is an iterator over integer-keyed table values: - t = {} - for i, v in f {'foo', 42, nil, nil, 'five'} do - t[i] = v - end - expect(t).to_equal {'foo', 42, nil, nil, 'five'} - - it ignores the dictionary part of a table: - t = {} - for i, v in f {'foo', 42, nil, nil, 'five'; bar='baz', qux='quux'} do - t[i] = v - end - expect(t).to_equal {'foo', 42, nil, nil, 'five'} - - it respects __len metamethod: - t = {} - for _, v in f(setmetatable({[2]=false}, {__len=function(self) return 4 end})) do - t[#t + 1] = tostring(v) - end - expect(table.concat(t, ',')).to_be 'nil,false,nil,nil' - - it works for an empty list: - t = {} - for i, v in f {} do - t[i] = v - end - expect(t).to_equal {} - - -- describe pairs: - - before: - f = M.pairs - - - context with bad arguments: - badargs.diagnose(f, 'std.pairs(table)') - - - it is an iterator over all table values: - t = {} - for k, v in f {'foo', bar='baz', 42} do - t[k] = v - end - expect(t).to_equal {'foo', bar='baz', 42} - - it respects __pairs metamethod: | - t = {} - for k, v in f(__pairs) do - t[k] = v - end - expect(t). - to_contain.a_permutation_of {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'} - - it works for an empty list: - t = {} - for k, v in f {} do - t[k] = v - end - expect(t).to_equal {} - - -- describe require: - - before: - f = M.require - - - context with bad arguments: - badargs.diagnose(f, 'std.require(string, ?string, ?string, ?string)') - - - it diagnoses non-existent module: - expect(f('module-not-exists', '', '')).to_raise 'module-not-exists' - - it diagnoses module too old: - expect(f('std', '9999', '9999')). - to_raise "require 'std' with at least version 9999," - - it diagnoses module too new: - expect(f('std', '0', '0')). - to_raise "require 'std' with version less than 0," - - context when the module version is compatible: - - it returns the module table: - expect(f('std', '0', '9999')).to_be(require 'std') - - it places no upper bound by default: - expect(f('std', '0')).to_be(require 'std') - - it places no lower bound by default: - expect(f 'std').to_be(require 'std') - - it uses _VERSION when version field is nil: - expect(luaproc [[ - package.loaded['poop'] = {_VERSION='41.1'} - f = require 'std'.require - print(f('poop', '41', '9999')._VERSION) - ]]).to_succeed_with '41.1\n' - - context with semantic versioning: - - before: - std = require 'std' - ver = std.version - std.version = '1.2.3' - - after: - std.version = ver - - it diagnoses module too old: - expect(f('std', '1.2.4')). - to_raise "require 'std' with at least version 1.2.4," - expect(f('std', '1.3')). - to_raise "require 'std' with at least version 1.3," - expect(f('std', '2.1.2')). - to_raise "require 'std' with at least version 2.1.2," - expect(f('std', '2')). - to_raise "require 'std' with at least version 2," - expect(f('std', '1.2.10')). - to_raise "require 'std' with at least version 1.2.10," - - it diagnoses module too new: - expect(f('std', nil, '1.2.2')). - to_raise "require 'std' with version less than 1.2.2," - expect(f('std', nil, '1.1')). - to_raise "require 'std' with version less than 1.1," - expect(f('std', nil, '1.1.2')). - to_raise "require 'std' with version less than 1.1.2," - expect(f('std', nil, '1')). - to_raise "require 'std' with version less than 1," - - it returns modules with version in range: - expect(f('std')).to_be(std) - expect(f('std', '1')).to_be(std) - expect(f('std', '1.2.3')).to_be(std) - expect(f('std', nil, '2')).to_be(std) - expect(f('std', nil, '1.3')).to_be(std) - expect(f('std', nil, '1.2.10')).to_be(std) - expect(f('std', '1.2.3', '1.2.4')).to_be(std) - - context with several numbers in version string: - - before: - std = require 'std' - ver = std.version - std.version = 'standard library for Lua 5.3 / 41.0.0' - - after: - std.version = ver - - it diagnoses module too old: - expect(f('std', '42')).to_raise() - - it diagnoses module too new: - expect(f('std', nil, '40')).to_raise() - - it returns modules with version in range: - expect(f('std')).to_be(std) - expect(f('std', '1')).to_be(std) - expect(f('std', '41')).to_be(std) - expect(f('std', nil, '42')).to_be(std) - expect(f('std', '41', '42')).to_be(std) - - -- describe ripairs: - - before: - f = M.ripairs - - - context with bad arguments: - badargs.diagnose(f, 'std.ripairs(table)') - - - it returns a function, the table and a number: - fn, t, i = f {1, 2, 3} - expect({type(fn), t, type(i)}).to_equal {'function', {1, 2, 3}, 'number'} - - it iterates over the array part of a table: - t, u = {1, 2, 3; a=4, b=5, c=6}, {} - for i, v in f(t) do - u[i] = v - end - expect(u).to_equal {1, 2, 3} - - it returns elements in reverse order: - t, u = {'one', 'two', 'five'}, {} - for _, v in f(t) do - u[#u + 1] = v - end - expect(u).to_equal {'five', 'two', 'one'} - - it respects __len metamethod: - t = {} - for i, v in f(__index) do - t[i] = v - end - expect(t).to_equal {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'} - t = {} - for _, v in f(__index) do - t[#t + 1] = v - end - expect(t).to_equal {'g', 'n', 'i', 'r', 't', 's', ' ', 'a'} - - it works with the empty list: - t = {} - for k, v in f {} do - t[k] = v - end - expect(t).to_equal {} - - -- describe rnpairs: - - before: - f = M.rnpairs - - - context with bad arguments: - badargs.diagnose(f, 'std.rnpairs(table)') - - - it returns a function, the table and a number: - fn, t, i = f {1, 2, nil, nil, 3} - expect({type(fn), t, type(i)}). - to_equal {'function', {1, 2, nil, nil, 3}, 'number'} - - it iterates over the array part of a table: - t, u = {1, 2, nil, nil, 3; a=4, b=5, c=6}, {} - for i, v in f(t) do - u[i] = v - end - expect(u).to_equal {1, 2, nil, nil, 3} - - it returns elements in reverse order: - t, u, i = {'one', 'two', nil, nil, 'five'}, {}, 1 - for _, v in f(t) do - u[i], i = v, i + 1 - end - expect(u).to_equal {'five', nil, nil, 'two', 'one'} - - it respects __len metamethod: - t = {} - for _, v in f(setmetatable({[2]=false}, {__len=function(self) return 4 end})) do - t[#t + 1] = tostring(v) - end - expect(table.concat(t, ',')).to_be 'nil,nil,false,nil' - - it works with the empty list: - t = {} - for k, v in f {} do - t[k] = v - end - expect(t).to_equal {} diff --git a/spec/string_spec.yaml b/spec/string_spec.yaml deleted file mode 100644 index 2fa47f2..0000000 --- a/spec/string_spec.yaml +++ /dev/null @@ -1,549 +0,0 @@ -# General Lua Libraries for Lua 5.1, 5.2 & 5.3 -# Copyright (C) 2011-2018 stdlib authors - -before: - base_module = 'string' - this_module = 'std.string' - global_table = '_G' - - extend_base = {'__concat', '__index', - 'caps', 'chomp', 'escape_pattern', 'escape_shell', - 'finds', 'format', 'ltrim', - 'numbertosi', 'ordinal_suffix', 'pad', - 'prettytostring', 'rtrim', 'split', - 'tfind', 'trim', 'wrap'} - - M = require(this_module) - getmetatable('').__concat = M.__concat - getmetatable('').__index = M.__index - -specify std.string: -- before: - subject = 'a string \n\n' - -- context when required: - - context by name: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by=this_module}). - to_equal {} - - it does not touch the core string table: - expect(show_apis {added_to=base_module, by=this_module}). - to_equal {} - - it contains apis from the core string table: - expect(show_apis {from=base_module, not_in=this_module}). - to_contain.a_permutation_of(extend_base) - - - context via the std module: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by='std'}). - to_equal {} - - it does not touch the core string table: - expect(show_apis {added_to=base_module, by='std'}). - to_equal {} - -- describe ..: - - it concatenates string arguments: - target = 'a string \n\n another string' - expect(subject .. ' another string').to_be(target) - - it stringifies non-string arguments: - argument = {'a table'} - expect(subject .. argument).to_be(subject .. '{1="a table"}') - - it stringifies nil arguments: - argument = nil - expect(subject .. argument). - to_be(string.format('%s%s', subject, require 'std.normalize'.str(argument))) - - it does not perturb the original subject: - original = subject - newstring = subject .. ' concatenate something' - expect(subject).to_be(original) - - -- describe caps: - - before: - f = M.caps - - - context with bad arguments: - badargs.diagnose(f, 'std.string.caps(string)') - - - it capitalises words of a string: - target = 'A String \n\n' - expect(f(subject)).to_be(target) - - it changes only the first letter of each word: - expect(f 'a stRiNg').to_be 'A StRiNg' - - it is available as a string metamethod: - expect(('a stRiNg'):caps()).to_be 'A StRiNg' - - it does not perturb the original subject: - original = subject - newstring = f(subject) - expect(subject).to_be(original) - - -- describe chomp: - - before: - target = 'a string \n' - f = M.chomp - - - context with bad arguments: - badargs.diagnose(f, 'std.string.chomp(string)') - - - it removes a single trailing newline from a string: - expect(f(subject)).to_be(target) - - it does not change a string with no trailing newline: - subject = 'a string ' - expect(f(subject)).to_be(subject) - - it is available as a string metamethod: - expect(subject:chomp()).to_be(target) - - it does not perturb the original subject: - original = subject - newstring = f(subject) - expect(subject).to_be(original) - - -- describe escape_pattern: - - before: - magic = {} - meta = '^$()%.[]*+-?' - for i = 1, string.len(meta) do - magic[meta:sub(i, i)] = true - end - f = M.escape_pattern - - - context with bad arguments: - badargs.diagnose(f, 'std.string.escape_pattern(string)') - - - context with each printable ASCII char: - - before: - subject, target = '', '' - for c = 32, 126 do - s = string.char(c) - subject = subject .. s - if magic[s] then - target = target .. '%' - end - target = target .. s - end - - 'it inserts a % before any non-alphanumeric in a string': - expect(f(subject)).to_be(target) - - it is available as a string metamethod: - expect(subject:escape_pattern()).to_be(target) - - it does not perturb the original subject: - original = subject - newstring = f(subject) - expect(subject).to_be(original) - - -- describe escape_shell: - - before: - f = M.escape_shell - - - context with bad arguments: - badargs.diagnose(f, 'std.string.escape_shell(string)') - - - context with each printable ASCII char: - - before: - subject, target = '', '' - for c = 32, 126 do - s = string.char(c) - subject = subject .. s - if s:match('[][ ()\\\'"]') then - target = target .. '\\' - end - target = target .. s - end - - 'it inserts a \\ before any shell metacharacters': - expect(f(subject)).to_be(target) - - it is available as a string metamethod: - expect(subject:escape_shell()).to_be(target) - - it does not perturb the original subject: - original = subject - newstring = f(subject) - expect(subject).to_be(original) - - 'it diagnoses non-string arguments': - if typecheck then - expect(f()).to_raise('string expected') - expect(f {'a table'}).to_raise('string expected') - end - - -- describe finds: - - before: - subject = 'abcd' - f = M.finds - - - context with bad arguments: - badargs.diagnose(f, 'std.string.finds(string, string, ?int, ?boolean|:plain)') - - - context given a complex nested list: - - before: - target = {{1, 2; capt={'a', 'b'}}, {3, 4; capt={'c', 'd'}}} - - it creates a list of pattern captures: - expect({f(subject, '(.)(.)')}).to_equal({target}) - - it is available as a string metamethod: - expect({subject:finds('(.)(.)')}).to_equal({target}) - - it creates an empty list where no captures are matched: - target = {} - expect({f(subject, '(x)')}).to_equal({target}) - - it creates an empty list for a pattern without captures: - target = {{1, 1; capt={}}} - expect({f(subject, 'a')}).to_equal({target}) - - it starts the search at a specified index into the subject: - target = {{8, 9; capt={'a', 'b'}}, {10, 11; capt={'c', 'd'}}} - expect({f('garbage' .. subject, '(.)(.)', 8)}).to_equal({target}) - - it does not perturb the original subject: - original = subject - newstring = f(subject, '...') - expect(subject).to_be(original) - - -- describe format: - - before: - subject = 'string=%s, number=%d' - - f = M.format - - - context with bad arguments: - badargs.diagnose(f, 'std.string.format(string, ?any*)') - - - it returns a single argument without attempting formatting: - expect(f(subject)).to_be(subject) - - it is available as a string metamethod: - expect(subject:format()).to_be(subject) - - it does not perturb the original subject: - original = subject - newstring = f(subject) - expect(subject).to_be(original) - - -- describe ltrim: - - before: - subject = ' \t\r\n a short string \t\r\n ' - - f = M.ltrim - - - context with bad arguments: - badargs.diagnose(f, 'std.string.ltrim(string, ?string)') - - - it removes whitespace from the start of a string: - target = 'a short string \t\r\n ' - expect(f(subject)).to_equal(target) - - it supports custom removal patterns: - target = '\r\n a short string \t\r\n ' - expect(f(subject, '[ \t\n]+')).to_equal(target) - - it is available as a string metamethod: - target = '\r\n a short string \t\r\n ' - expect(subject:ltrim('[ \t\n]+')).to_equal(target) - - it does not perturb the original subject: - original = subject - newstring = f(subject, '%W') - expect(subject).to_be(original) - - -- describe numbertosi: - - before: - f = M.numbertosi - - - context with bad arguments: - badargs.diagnose(f, 'std.string.numbertosi(number|string)') - - - it returns a number using SI suffixes: - target = {'1e-9', '1y', '1z', '1a', '1f', '1p', '1n', '1mu', '1m', '1', - '1k', '1M', '1G', '1T', '1P', '1E', '1Z', '1Y', '1e9'} - subject = {} - for n = -28, 28, 3 do - m = 10 *(10 ^ n) - table.insert(subject, f(m)) - end - expect(subject).to_equal(target) - - it coerces string arguments to a number: - expect(f '1000').to_be '1k' - - -- describe ordinal_suffix: - - before: - f = M.ordinal_suffix - - - context with bad arguments: - badargs.diagnose(f, 'std.string.ordinal_suffix(int|string)') - - - it returns the English suffix for a number: - subject, target = {}, {} - for n = -120, 120 do - suffix = 'th' - m = math.abs(n) % 10 - if m == 1 and math.abs(n) % 100 ~= 11 then - suffix = 'st' - elseif m == 2 and math.abs(n) % 100 ~= 12 then - suffix = 'nd' - elseif m == 3 and math.abs(n) % 100 ~= 13 then - suffix = 'rd' - end - table.insert(target, n .. suffix) - table.insert(subject, n .. f(n)) - end - expect(subject).to_equal(target) - - it coerces string arguments to a number: - expect(f '-91').to_be 'st' - - -- describe pad: - - before: - width = 20 - - f = M.pad - - - context with bad arguments: - badargs.diagnose(f, 'std.string.pad(string, int, ?string)') - - - context when string is shorter than given width: - - before: - subject = 'short string' - - it right pads a string to the given width with spaces: - target = 'short string ' - expect(f(subject, width)).to_be(target) - - it left pads a string to the given negative width with spaces: - width = -width - target = ' short string' - expect(f(subject, width)).to_be(target) - - it is available as a string metamethod: - target = 'short string ' - expect(subject:pad(width)).to_be(target) - - - context when string is longer than given width: - - before: - subject = "a string that's longer than twenty characters" - - it truncates a string to the given width: - target = "a string that's long" - expect(f(subject, width)).to_be(target) - - it left pads a string to given width with spaces: - width = -width - target = 'an twenty characters' - expect(f(subject, width)).to_be(target) - - it is available as a string metamethod: - target = "a string that's long" - expect(subject:pad(width)).to_be(target) - - - it does not perturb the original subject: - original = subject - newstring = f(subject, width) - expect(subject).to_be(original) - - -- describe prettytostring: - - before: - f = M.prettytostring - - - context with bad arguments: - badargs.diagnose(f, 'std.string.prettytostring(?any, ?string, ?string)') - - - it renders nil exactly like system tostring: - expect(f(nil)).to_be(tostring(nil)) - - it renders booleans exactly like system tostring: - expect(f(true)).to_be(tostring(true)) - expect(f(false)).to_be(tostring(false)) - - it renders numbers exactly like system tostring: - n = 8723643 - expect(f(n)).to_be(tostring(n)) - - it renders functions exactly like system tostring: - expect(f(f)).to_be(tostring(f)) - - it renders strings with format '%q' styling: - s = 'a string' - expect(f(s)).to_be(string.format('%q', s)) - - it renders empty tables as a pair of braces: - expect(f {}).to_be('{\n}') - - it renders an array prettily: - a = {'one', 'two', 'three'} - expect(f(a, '')). - to_be '{\n[1] = "one",\n[2] = "two",\n[3] = "three",\n}' - - it renders a table prettily: - t = {one=true, two=2, three={3}} - expect(f(t, '')). - to_be '{\none = true,\nthree =\n{\n[1] = 3,\n},\ntwo = 2,\n}' - - it renders table keys in table.sort order: - t = {one=3, two=5, three=4, four=2, five=1} - expect(f(t, '')). - to_be '{\nfive = 1,\nfour = 2,\none = 3,\nthree = 4,\ntwo = 5,\n}' - - it renders keys with invalid symbol names in long hand: - t = {_=0, word=0, ['?']=1, ['a-key']=1, ['[]']=1} - expect(f(t, '')). - to_be '{\n["?"] = 1,\n["[]"] = 1,\n_ = 0,\n["a-key"] = 1,\nword = 0,\n}' - - -- describe rtrim: - - before: - subject = ' \t\r\n a short string \t\r\n ' - - f = M.rtrim - - - context with bad arguments: - badargs.diagnose(f, 'std.string.rtrim(string, ?string)') - - - it removes whitespace from the end of a string: - target = ' \t\r\n a short string' - expect(f(subject)).to_equal(target) - - it supports custom removal patterns: - target = ' \t\r\n a short string \t\r' - expect(f(subject, '[ \t\n]+')).to_equal(target) - - it is available as a string metamethod: - target = ' \t\r\n a short string \t\r' - expect(subject:rtrim('[ \t\n]+')).to_equal(target) - - it does not perturb the original subject: - original = subject - newstring = f(subject, '%W') - expect(subject).to_be(original) - - -- describe split: - - before: - target = {'first', 'the second one', 'final entry'} - subject = table.concat(target, ', ') - - f = M.split - - - context with bad arguments: - badargs.diagnose(f, 'std.string.split(string, ?string)') - - - it falls back to '%s+' when no pattern is given: - expect(f(subject)). - to_equal {'first,', 'the', 'second', 'one,', 'final', 'entry'} - - it returns a one-element list for an empty string: - expect(f('', ', ')).to_equal {''} - - it makes a table of substrings delimited by a separator: - expect(f(subject, ', ')).to_equal(target) - - it returns n+1 elements for n separators: - expect(f(subject, 'zero')).to_have_size(1) - expect(f(subject, 'c')).to_have_size(2) - expect(f(subject, 's')).to_have_size(3) - expect(f(subject, 't')).to_have_size(4) - expect(f(subject, 'e')).to_have_size(5) - - it returns an empty string element for consecutive separators: - expect(f('xyzyzxy', 'yz')).to_equal {'x', '', 'xy'} - - it returns an empty string element when starting with separator: - expect(f('xyzyzxy', 'xyz')).to_equal {'', 'yzxy'} - - it returns an empty string element when ending with separator: - expect(f('xyzyzxy', 'zxy')).to_equal {'xyzy', ''} - - it returns a table of 1-character strings for '' separator: - expect(f('abcdef', '')).to_equal {'', 'a', 'b', 'c', 'd', 'e', 'f', ''} - - it is available as a string metamethod: - expect(subject:split ', ').to_equal(target) - expect(('/foo/bar/baz.quux'):split '/'). - to_equal {'', 'foo', 'bar', 'baz.quux'} - - it does not perturb the original subject: - original = subject - newstring = f(subject, 'e') - expect(subject).to_be(original) - - it takes a Lua pattern as a separator: - expect(f(subject, '%s+')). - to_equal {'first,', 'the', 'second', 'one,', 'final', 'entry'} - - -- describe tfind: - - before: - subject = 'abc' - - f = M.tfind - - - context with bad arguments: - badargs.diagnose(f, 'std.string.tfind(string, string, ?int, ?boolean|:plain)') - - - it creates a list of pattern captures: - target = {1, 3, {'a', 'b', 'c'}} - expect({f(subject, '(.)(.)(.)')}).to_equal(target) - - it creates an empty list where no captures are matched: - target = {nil, nil, {}} - expect({f(subject, '(x)(y)(z)')}).to_equal(target) - - it creates an empty list for a pattern without captures: - target = {1, 1, {}} - expect({f(subject, 'a')}).to_equal(target) - - it starts the search at a specified index into the subject: - target = {8, 10, {'a', 'b', 'c'}} - expect({f('garbage' .. subject, '(.)(.)(.)', 8)}).to_equal(target) - - it is available as a string metamethod: - target = {8, 10, {'a', 'b', 'c'}} - expect({('garbage' .. subject):tfind('(.)(.)(.)', 8)}).to_equal(target) - - it does not perturb the original subject: - original = subject - newstring = f(subject, '...') - expect(subject).to_be(original) - - -- describe trim: - - before: - subject = ' \t\r\n a short string \t\r\n ' - - f = M.trim - - - context with bad arguments: - badargs.diagnose(f, 'std.string.trim(string, ?string)') - - - it removes whitespace from each end of a string: - target = 'a short string' - expect(f(subject)).to_equal(target) - - it supports custom removal patterns: - target = '\r\n a short string \t\r' - expect(f(subject, '[ \t\n]+')).to_equal(target) - - it is available as a string metamethod: - target = '\r\n a short string \t\r' - expect(subject:trim('[ \t\n]+')).to_equal(target) - - it does not perturb the original subject: - original = subject - newstring = f(subject, '%W') - expect(subject).to_be(original) - - -- describe wrap: - - before: - subject = 'This is a collection of Lua libraries for Lua 5.1 ' .. - 'and 5.2. The libraries are copyright by their authors 2000' .. - '-2015 (see the AUTHORS file for details), and released und' .. - 'er the MIT license (the same license as Lua itself). There' .. - ' is no warranty.' - - f = M.wrap - - - context with bad arguments: - badargs.diagnose(f, 'std.string.wrap(string, ?int, ?int, ?int)') - - - it inserts newlines to wrap a string: - target = 'This is a collection of Lua libraries for Lua 5.1 a' .. - 'nd 5.2. The libraries are\ncopyright by their authors 2000' .. - '-2015 (see the AUTHORS file for details), and\nreleased un' .. - 'der the MIT license (the same license as Lua itself). Ther' .. - 'e is no\nwarranty.' - expect(f(subject)).to_be(target) - - it honours a column width parameter: - target = 'This is a collection of Lua libraries for Lua 5.1 a' .. - 'nd 5.2. The libraries\nare copyright by their authors 2000' .. - '-2015 (see the AUTHORS file for\ndetails), and released un' .. - 'der the MIT license (the same license as Lua\nitself). The' .. - 're is no warranty.' - expect(f(subject, 72)).to_be(target) - - it supports indenting by a fixed number of columns: - target = ' This is a collection of Lua libraries for L' .. - 'ua 5.1 and 5.2. The\n libraries are copyright by th' .. - 'eir authors 2000-2015 (see the\n AUTHORS file for d' .. - 'etails), and released under the MIT license\n (the ' .. - 'same license as Lua itself). There is no warranty.' - expect(f(subject, 72, 8)).to_be(target) - - context given a long unwrapped string: - - before: - target = ' This is a collection of Lua libraries for Lua 5' .. - '.1 and 5.2.\n The libraries are copyright by their author' .. - 's 2000-2015 (see\n the AUTHORS file for details), and rel' .. - 'eased under the MIT\n license (the same license as Lua it' .. - 'self). There is no\n warranty.' - - it can indent the first line differently: - expect(f(subject, 64, 2, 4)).to_be(target) - - it is available as a string metamethod: - expect(subject:wrap(64, 2, 4)).to_be(target) - - it does not perturb the original subject: - original = subject - newstring = f(subject, 55, 5) - expect(subject).to_be(original) - - it diagnoses indent greater than line width: - expect(f(subject, 10, 12)).to_raise('less than the line width') - expect(f(subject, 99, 99)).to_raise('less than the line width') - - it diagnoses non-string arguments: - if have_typecheck then - expect(f()).to_raise('string expected') - expect(f {'a table'}).to_raise('string expected') - end diff --git a/spec/table_spec.yaml b/spec/table_spec.yaml deleted file mode 100644 index d9fed0c..0000000 --- a/spec/table_spec.yaml +++ /dev/null @@ -1,589 +0,0 @@ -# General Lua Libraries for Lua 5.1, 5.2 & 5.3 -# Copyright (C) 2011-2018 stdlib authors - -before: | - base_module = 'table' - this_module = 'std.table' - global_table = '_G' - - extend_base = {'clone', 'clone_select', 'depair', 'empty', - 'enpair', 'insert', 'invert', 'keys', 'maxn', - 'merge', 'merge_select', 'new', - 'pack', 'project', 'remove', 'size', 'sort', - 'unpack', 'values'} - - M = require(this_module) - - -specify std.table: -- context when required: - - context by name: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by=this_module}). - to_equal {} - - it does not touch the core table table: - expect(show_apis {added_to=base_module, by=this_module}). - to_equal {} - - it contains apis from the core table table: - expect(show_apis {from=base_module, not_in=this_module}). - to_contain.a_permutation_of(extend_base) - - - context via the std module: - - it does not touch the global table: - expect(show_apis {added_to=global_table, by='std'}).to_equal {} - - it does not touch the core table table: - expect(show_apis {added_to=base_module, by='std'}).to_equal {} - - -- describe clone: - - before: - subject = {k1={'v1'}, k2={'v2'}, k3={'v3'}} - withmt = setmetatable(M.clone(subject), {'meta!'}) - - f = M.clone - - - context with bad arguments: - badargs.diagnose(f, 'std.table.clone(table, [table], ?boolean|:nometa)') - - - it does not just return the subject: - expect(f(subject)).not_to_be(subject) - - it does copy the subject: - expect(f(subject)).to_equal(subject) - - it only makes a shallow copy of field values: - expect(f(subject).k1).to_be(subject.k1) - - it does not perturb the original subject: - target = {k1=subject.k1, k2=subject.k2, k3=subject.k3} - copy = f(subject) - expect(subject).to_equal(target) - expect(subject).to_be(subject) - - - context with metatables: - - it copies the metatable by default: - expect(getmetatable(f(withmt))).to_be(getmetatable(withmt)) - - it treats non-table arg2 as nometa parameter: - expect(getmetatable(f(withmt, ':nometa'))).to_be(nil) - - it treats table arg2 as a map parameter: - expect(getmetatable(f(withmt, {}))).to_be(getmetatable(withmt)) - - it supports 3 arguments with nometa as arg3: - expect(getmetatable(f(withmt, {}, ':nometa'))).to_be(nil) - - - context when renaming some keys: - - it renames during cloning: - target = {newkey=subject.k1, k2=subject.k2, k3=subject.k3} - expect(f(subject, {k1 = 'newkey'})).to_equal(target) - - it does not perturb the value in the renamed key field: - expect(f(subject, {k1 = 'newkey'}).newkey).to_be(subject.k1) - - -- describe clone_select: - - before: - subject = {k1={'v1'}, k2={'v2'}, k3={'v3'}} - withmt = setmetatable(M.clone(subject), {'meta!'}) - - f = M.clone_select - - - context with bad arguments: - badargs.diagnose(f, 'std.table.clone_select(table, [table], ?boolean|:nometa)') - - - it does not just return the subject: - expect(f(subject)).not_to_be(subject) - - it copies the keys selected: - expect(f(subject, {'k1', 'k2'})).to_equal({k1={'v1'}, k2={'v2'}}) - - it does copy the subject when supplied with a full list of keys: - expect(f(subject, {'k1', 'k2', 'k3'})).to_equal(subject) - - it only makes a shallow copy: - expect(f(subject, {'k1'}).k1).to_be(subject.k1) - - it does not perturb the original subject: - target = {k1=subject.k1, k2=subject.k2, k3=subject.k3} - copy = f(subject, {'k1', 'k2', 'k3'}) - expect(subject).to_equal(target) - expect(subject).to_be(subject) - - - context with metatables: - - it treats non-table arg2 as nometa parameter: - expect(getmetatable(f(withmt, ':nometa'))).to_be(nil) - - it treats table arg2 as a map parameter: - expect(getmetatable(f(withmt, {}))).to_be(getmetatable(withmt)) - expect(getmetatable(f(withmt, {'k1'}))).to_be(getmetatable(withmt)) - - it supports 3 arguments with nometa as arg3: - expect(getmetatable(f(withmt, {}, ':nometa'))).to_be(nil) - expect(getmetatable(f(withmt, {'k1'}, ':nometa'))).to_be(nil) - - -- describe depair: - - before: - t = {'first', 'second', third = 4} - l = M.enpair(t) - - f = M.depair - - - context with bad arguments: - badargs.diagnose(f, 'std.table.depair(list of lists)') - - - it returns a primitive table: - expect(objtype(f(l))).to_be 'table' - - it works with an empty table: - expect(f {}).to_equal {} - - it is the inverse of enpair: - expect(f(l)).to_equal(t) - - -- describe empty: - - before: - f = M.empty - - - context with bad arguments: - badargs.diagnose(f, 'std.table.empty(table)') - - - it returns true for an empty table: - expect(f {}).to_be(true) - expect(f {nil}).to_be(true) - - it returns false for a non-empty table: - expect(f {'stuff'}).to_be(false) - expect(f {{}}).to_be(false) - expect(f {false}).to_be(false) - - -- describe enpair: - - before: - t = {'first', 'second', third = 4} - l = M.enpair(t) - - f = M.enpair - - - context with bad arguments: - badargs.diagnose(f, 'std.table.enpair(table)') - - - it returns a table: - expect(objtype(f(t))).to_be 'table' - - it works for an empty table: - expect(f {}).to_equal {} - - it turns a table into a table of pairs: - expect(f(t)).to_equal {{1, 'first'}, {2, 'second'}, {'third', 4}} - - it is the inverse of depair: - expect(f(t)).to_equal(l) - - -- describe insert: - - before: - f, badarg = init(M, this_module, 'insert') - - - context with bad arguments: - badargs.diagnose(f, 'std.table.insert(table, [int], any)') - - examples { - ['it diagnoses more than 2 arguments with no pos'] = function() - pending '#issue 76' - expect(f({}, false, false)).to_raise(badarg(3)) - end - } - examples { - ['it diagnoses out of bounds pos arguments'] = function() - expect(f({}, 0, 'x')).to_raise 'position 0 out of bounds' - expect(f({}, 2, 'x')).to_raise 'position 2 out of bounds' - expect(f({1}, 5, 'x')).to_raise 'position 5 out of bounds' - end - } - - - it returns the modified table: - t = {} - expect(f(t, 1)).to_be(t) - - it append a new element at the end by default: - expect(f({1, 2}, 'x')).to_equal {1, 2, 'x'} - - it fills holes by default: - expect(f({1, 2, [5]=3}, 'x')).to_equal {1, 2, 'x', [5]=3} - - it respects __len when appending: - t = setmetatable({1, 2, [5]=3}, {__len = function() return 42 end}) - expect(f(t, 'x')).to_equal {1, 2, [5]=3, [43]='x'} - - it moves other elements up if necessary: - expect(f({1, 2}, 1, 'x')).to_equal {'x', 1, 2} - expect(f({1, 2}, 2, 'x')).to_equal {1, 'x', 2} - expect(f({1, 2}, 3, 'x')).to_equal {1, 2, 'x'} - - it inserts a new element according to pos argument: - expect(f({}, 1, 'x')).to_equal {'x'} - - -- describe invert: - - before: - subject = {k1=1, k2=2, k3=3} - - f = M.invert - - - context with bad arguments: - badargs.diagnose(f, 'std.table.invert(table)') - - - it returns a new table: - expect(f(subject)).not_to_be(subject) - - it inverts keys and values in the returned table: - expect(f(subject)).to_equal {'k1', 'k2', 'k3'} - - it is reversible: - expect(f(f(subject))).to_equal(subject) - - it seems to copy a list of 1..n numbers: - subject = {1, 2, 3} - expect(f(subject)).to_copy(subject) - - -- describe keys: - - before: - subject = {k1=1, k2=2, k3=3} - - f = M.keys - - - context with bad arguments: - badargs.diagnose(f, 'std.table.keys(table)') - - - it returns an empty list when subject is empty: - expect(f {}).to_equal {} - - it makes a list of table keys: - cmp = function(a, b) - return a < b - end - expect(M.sort(f(subject), cmp)).to_equal {'k1', 'k2', 'k3'} - - it does not guarantee stable ordering: - subject = {} - -- is this a good test? there is a vanishingly small possibility the - -- returned table will have all 10000 keys in the same order... - for i = 10000, 1, -1 do - table.insert(subject, i) - end - expect(f(subject)).not_to_equal(subject) - - -- describe maxn: - - before: - f = M.maxn - - - context with bad arguments: - badargs.diagnose(f, 'std.table.maxn(table)') - - - it returns the largest numeric key of a table: - expect(f {'a', 'b', 'c'}).to_be(3) - expect(f {1, 2, 5, a=10, 3}).to_be(4) - - it works with an empty table: - expect(f {}).to_be(0) - - it ignores holes: - expect(f {1, 2, [5]=3}).to_be(5) - - it ignores __len metamethod: - t = setmetatable({1, 2, [5]=3}, {__len = function() return 42 end}) - expect(f(t)).to_be(5) - - -- describe merge: - - before: | - -- Additional merge keys which are moderately unusual - t1 = {k1={'v1'}, k2='if', k3={'?'}} - t2 = {['if']=true, [{'?'}]=false, _='underscore', k3=t1.k1} - t1mt = setmetatable(M.clone(t1), {'meta!'}) - target = {} - for k, v in pairs(t1) do - target[k] = v - end - for k, v in pairs(t2) do - target[k] = v - end - - f, badarg = init(M, this_module, 'merge') - - - context with bad arguments: - badargs.diagnose(f, 'std.table.merge(table, table, [table], ?boolean|:nometa)') - - examples { - ['it diagnoses more than 2 arguments with no pos'] = function() - pending '#issue 76' - expect(f({}, {}, ':nometa', false)).to_raise(badarg(4)) - end - } - - - it does not create a whole new table: - expect(f(t1, t2)).to_be(t1) - - it does not change t1 when t2 is empty: - expect(f(t1, {})).to_be(t1) - - it copies t2 when t1 is empty: - expect(f({}, t1)).to_copy(t1) - - it merges keys from t2 into t1: - expect(f(t1, t2)).to_equal(target) - - it gives precedence to values from t2: - original = M.clone(t1) - m = f(t1, t2) -- Merge is destructive, do it once only. - expect(m.k3).to_be(t2.k3) - expect(m.k3).not_to_be(original.k3) - - it only makes a shallow copy of field values: - expect(f({}, t1).k1).to_be(t1.k1) - - - context with metatables: - - it copies the metatable by default: - expect(getmetatable(f({}, t1mt))).to_be(getmetatable(t1mt)) - expect(getmetatable(f({}, t1mt, {'k1'}))).to_be(getmetatable(t1mt)) - - it treats non-table arg3 as nometa parameter: - expect(getmetatable(f({}, t1mt, ':nometa'))).to_be(nil) - - it treats table arg3 as a map parameter: - expect(getmetatable(f({}, t1mt, {}))).to_be(getmetatable(t1mt)) - expect(getmetatable(f({}, t1mt, {'k1'}))).to_be(getmetatable(t1mt)) - - it supports 4 arguments with nometa as arg4: - expect(getmetatable(f({}, t1mt, {}, ':nometa'))).to_be(nil) - expect(getmetatable(f({}, t1mt, {'k1'}, ':nometa'))).to_be(nil) - - - context when renaming some keys: - - it renames during merging: - target = {newkey=t1.k1, k2=t1.k2, k3=t1.k3} - expect(f({}, t1, {k1 = 'newkey'})).to_equal(target) - - it does not perturb the value in the renamed key field: - expect(f({}, t1, {k1 = 'newkey'}).newkey).to_be(t1.k1) - - -- describe merge_select: - - before: | - -- Additional merge keys which are moderately unusual - tablekey = {'?'} - t1 = {k1={'v1'}, k2='if', k3={'?'}} - t1mt = setmetatable(M.clone(t1), {'meta!'}) - t2 = {['if']=true, [tablekey]=false, _='underscore', k3=t1.k1} - t2keys = {'if', tablekey, '_', 'k3'} - target = {} - for k, v in pairs(t1) do - target[k] = v - end - for k, v in pairs(t2) do - target[k] = v - end - - f, badarg = init(M, this_module, 'merge_select') - - - context with bad arguments: - badargs.diagnose(f, 'std.table.merge_select(table, table, [table], ?boolean|:nometa)') - - examples { - ['it diagnoses more than 2 arguments with no pos'] = function() - pending '#issue 76' - expect(f({}, {}, ':nometa', false)).to_raise(badarg(4)) - end - } - - - it does not create a whole new table: - expect(f(t1, t2)).to_be(t1) - - it does not change t1 when t2 is empty: - expect(f(t1, {})).to_be(t1) - - it does not change t1 when key list is empty: - expect(f(t1, t2, {})).to_be(t1) - - it copies the named fields: - expect(f({}, t2, t2keys)).to_equal(t2) - - it makes a shallow copy: - expect(f({}, t1, {'k1'}).k1).to_be(t1.k1) - - it copies exactly named fields of t2 when t1 is empty: - expect(f({}, t1, {'k1', 'k2', 'k3'})).to_copy(t1) - - it merges keys from t2 into t1: - expect(f(t1, t2, t2keys)).to_equal(target) - - it gives precedence to values from t2: - original = M.clone(t1) - m = f(t1, t2, t2keys) -- Merge is destructive, do it once only. - expect(m.k3).to_be(t2.k3) - expect(m.k3).not_to_be(original.k3) - - - context with metatables: - - it copies the metatable by default: - expect(getmetatable(f({}, t1mt))).to_be(getmetatable(t1mt)) - expect(getmetatable(f({}, t1mt, {'k1'}))).to_be(getmetatable(t1mt)) - - it treats non-table arg3 as nometa parameter: - expect(getmetatable(f({}, t1mt, ':nometa'))).to_be(nil) - - it treats table arg3 as a map parameter: - expect(getmetatable(f({}, t1mt, {}))).to_be(getmetatable(t1mt)) - expect(getmetatable(f({}, t1mt, {'k1'}))).to_be(getmetatable(t1mt)) - - it supports 4 arguments with nometa as arg4: - expect(getmetatable(f({}, t1mt, {}, ':nometa'))).to_be(nil) - expect(getmetatable(f({}, t1mt, {'k1'}, ':nometa'))).to_be(nil) - - -- describe new: - - before: - f = M.new - - - context with bad arguments: - badargs.diagnose(f, 'std.table.new(?any, ?table)') - - - context when not setting a default: - - before: default = nil - - it returns a new table when nil is passed: - expect(f(default, nil)).to_equal {} - - it returns any table passed in: - t = {'unique table'} - expect(f(default, t)).to_be(t) - - - context when setting a default: - - before: - default = 'default' - - it returns a new table when nil is passed: - expect(f(default, nil)).to_equal {} - - it returns any table passed in: - t = {'unique table'} - expect(f(default, t)).to_be(t) - - - it returns the stored value for existing keys: - t = f('default') - v = {'unique value'} - t[1] = v - expect(t[1]).to_be(v) - - it returns the constructor default for unset keys: - t = f('default') - expect(t[1]).to_be 'default' - - it returns the actual default object: - default = {'unique object'} - t = f(default) - expect(t[1]).to_be(default) - - -- describe pack: - - before: - unpack = unpack or table.unpack - t = {'one', 'two', 'five', n=3} - f = M.pack - - it creates an empty table with no arguments: - expect(f()).to_equal {n=0} - - it creates a table with arguments as elements: - expect(f('one', 'two', 'five')).to_equal(t) - - it is the inverse operation to unpack: - expect(f(unpack(t))).to_equal(t) - - it saves the tuple length in field n: - expect(f(1, 2, 5).n).to_be(3) - expect(f('', false, nil).n).to_be(3) - expect(f(nil, nil, nil).n).to_be(3) - - -- describe project: - - before: - l = { - {first = false, second = true, third = true}, - {first = 1, second = 2, third = 3}, - {first = '1st', second = '2nd', third = '3rd'}, - } - - f = M.project - - - context with bad arguments: - badargs.diagnose(f, 'std.table.project(any, list of tables)') - - - it returns a table: - expect(objtype(f('third', l))).to_be 'table' - - it works with an empty table: - expect(f('third', {})).to_equal {} - - it projects a table of fields from a table of tables: - expect(f('third', l)).to_equal {true, 3, '3rd'} - - it projects fields with a falsey value correctly: - expect(f('first', l)).to_equal {false, 1, '1st'} - - -- describe remove: - - before: - f = M.remove - - - context with bad arguments: - badargs.diagnose(f, 'std.table.remove(table, ?int)') - - examples { - ['it diagnoses out of bounds pos arguments'] = function() - expect(f({1}, 0)).to_raise 'position 0 out of bounds' - expect(f({1}, 3)).to_raise 'position 3 out of bounds' - expect(f({1}, 5)).to_raise 'position 5 out of bounds' - end - } - - - it returns the removed element: - t = {'one', 'two', 'five'} - expect(f({'one', 2, 5}, 1)).to_be 'one' - - it removes an element from the end by default: - expect(f {1, 2, 'five'}).to_be 'five' - - it ignores holes: - t = {'second', 'first', [5]='invisible'} - expect(f(t)).to_be 'first' - expect(f(t)).to_be 'second' - - it respects __len when defaulting pos: - t = setmetatable({1, 2, [43]='invisible'}, {__len = function() return 42 end}) - expect(f(t)).to_be(nil) - expect(f(t)).to_be(nil) - expect(t).to_equal {1, 2, [43]='invisible'} - - it moves other elements down if necessary: - t = {1, 2, 5, 'third', 'first', 'second', 42} - expect(f(t, 5)).to_be 'first' - expect(t).to_equal {1, 2, 5, 'third', 'second', 42} - expect(f(t, 5)).to_be 'second' - expect(t).to_equal {1, 2, 5, 'third', 42} - expect(f(t, 4)).to_be 'third' - expect(t).to_equal {1, 2, 5, 42} - - -- describe size: - - before: | - -- - 1 - ------- 2 ------- -- 3 -- - subject = {'one', {{'two'}, 'three'}, four=5} - - f = M.size - - - context with bad arguments: - badargs.diagnose(f, 'std.table.size(table)') - - - it counts the number of keys in a table: - expect(f(subject)).to_be(3) - - it counts no keys in an empty table: - expect(f {}).to_be(0) - - -- describe sort: - - before: - subject = {5, 2, 4, 1, 0, 3} - target = {0, 1, 2, 3, 4, 5} - cmp = function(a, b) return a < b end - - f = M.sort - - - context with bad arguments: - badargs.diagnose(f, 'std.table.sort(table, ?function)') - - - it sorts elements in place: - f(subject, cmp) - expect(subject).to_equal(target) - - it returns the sorted table: - expect(f(subject, cmp)).to_equal(target) - - -- describe unpack: - - before: - t = {'one', 'two', 'five'} - f = M.unpack - - it returns nil for an empty table: - expect(f {}).to_be(nil) - - it returns numeric indexed table elements: - expect({f(t)}).to_equal(t) - - it respects __len metamethod: - function two(t) - return setmetatable(t, {__len=function() return 2 end}) - end - expect(pack(f(two {})).n).to_be(2) - expect(pack(f(two(t))).n).to_be(2) - - it returns holes in numeric indices as nil: - expect({f {nil, 2}}).to_equal {[2] = 2} - expect({f {nil, nil, 3}}).to_equal {[3] = 3} - expect({f {1, nil, nil, 4}}).to_equal {1, [4] = 4} - - it is the inverse operation to pack: - expect({f(M.pack('one', 'two', 'five'))}).to_equal(t) - - -- describe values: - - before: - subject = {k1={1}, k2={2}, k3={3}} - - f = M.values - - - context with bad arguments: - badargs.diagnose(f, 'std.table.values(table)') - - - it returns an empty list when subject is empty: - expect(f {}).to_equal {} - - it makes a list of table values: - cmp = function(a, b) return a[1] < b[1] end - expect(M.sort(f(subject), cmp)).to_equal {{1}, {2}, {3}} - - it does guarantee stable ordering: - subject = {} - -- is this a good test? or just requiring an implementation quirk? - for i = 10000, 1, -1 do - table.insert(subject, i) - end - expect(f(subject)).to_equal(subject) diff --git a/stdlib-git-1.rockspec b/stdlib-git-1.rockspec deleted file mode 100644 index 504aee8..0000000 --- a/stdlib-git-1.rockspec +++ /dev/null @@ -1,51 +0,0 @@ -local _MODREV, _SPECREV = 'git', '-1' - -package = 'stdlib' -version = _MODREV .. _SPECREV - -description = { - summary = 'General Lua Libraries', - detailed = [[ - stdlib is a library of modules for common programming tasks, - including list and table operations, and pretty-printing. - ]], - homepage = 'http://lua-stdlib.github.io/lua-stdlib', - license = 'MIT/X11', -} - -source = (function(gitp) - if gitp then - return { - url = 'git://github.com/lua-stdlib/lua-stdlib.git', - } - else - return { - url = 'http://github.com/lua-stdlib/lua-stdlib/archive/v' .. _MODREV .. '.zip', - dir = 'lua-stdlib-' .. _MODREV, - } - end -end)(_MODREV == 'git') - -dependencies = { - 'lua >= 5.1, < 5.4', - 'std._debug', - 'std.normalize >= 2.0', -} - -if _MODREV == 'git' then - dependencies[#dependencies + 1] = 'ldoc' -end - -build = { - type = 'builtin', - modules = { - std = 'lib/std/init.lua', - ['std._base'] = 'lib/std/_base.lua', - ['std.debug'] = 'lib/std/debug.lua', - ['std.io'] = 'lib/std/io.lua', - ['std.math'] = 'lib/std/math.lua', - ['std.package'] = 'lib/std/package.lua', - ['std.string'] = 'lib/std/string.lua', - ['std.table'] = 'lib/std/table.lua', - }, -}