Penlight Documentation

# Module `pl.utils`

Generally useful routines.

See the Guide.

Dependencies: pl.compat, all exported fields and functions from pl.compat are also available in this module.

## Functions

pack (...) | pack an argument list into a table.
unpack (t[, i[, j]]) | unpack a table and return its contents.
printf (fmt, ...) | print an arbitrary number of arguments using a format.
fprintf (f, fmt, ...) | write an arbitrary number of arguments to a file using a format.
import (t, T) | take a table and 'inject' it into the local namespace.
choose (cond, value1, value2) | return either of two values, depending on a condition.
array_tostring (t[, temp[, tostr]]) | convert an array of values to strings.
is_type (obj, tp) | is the object of the specified type?
npairs (t[, i_start=1[, i_end=t.n or #t[, step=1]]]) | an iterator with indices, similar to ipairs, but with a range.
kpairs (t) | an iterator over all non-integer keys (inverse of ipairs).

## Tables

patterns | Some standard patterns
stdmt | Standard meta-tables as used by other Penlight modules

## Error handling

assert_arg (n, val, tp, verify, msg, lev) | assert that the given argument is in fact of the correct type.
enum (...) | creates an Enum or constants lookup table for improved error handling.
function_arg (idx, f, msg) | process a function argument.
assert_string (n, val) | assert the common case that the argument is a string.
on_error (mode) | control the error strategy used by Penlight.
raise (err) | used by Penlight functions to return errors.

## File handling

readfile (filename, is_bin) | return the contents of a file as a string
writefile (filename, str, is_bin) | write a string to a file
readlines (filename) | return the contents of a file as a list of lines

## OS functions

executeex (cmd, bin) | execute a shell command and return the output.
quote_arg (argument) | Quote and escape an argument of a command.
quit ([code], msg, ...) | error out of this program gracefully.

## String functions

escape (s) | escape any Lua 'magic' characters in a string
split (s, re, plain, n) | split a string into a list of strings separated by a delimiter.
splitv (s, re, plain, n) | split a string into a number of return values.

## Functional

memoize (func) | 'memoize' a function (cache returned value for next call).
add_function_factory (mt, fun) | associate a function factory with a type.
string_lambda (lf) | an anonymous function as a string.
bind1 (fn, p) | bind the first argument of the function to a value.
bind2 (fn, p) | bind the second argument of the function to a value.

## Deprecation

set_deprecation_func (func) | Sets a deprecation warning function.
raise_deprecation (opts) | raises a deprecation warning.

## Functions

pack (...)
  pack an argument list into a table.

  ### Parameters:

  - ... any arguments

  ### Returns:

  a table with field `n` set to the length

  ### See also:

  - compat.pack
  - utils.npairs
  - utils.unpack
unpack (t[, i[, j]])
  unpack a table and return its contents.

  NOTE: this implementation differs from the Lua implementation in the way that this one DOES honor the `n` field in the table `t`, such that it is 'nil-safe'.

  ### Parameters:

  - t table to unpack
  - i index from which to start unpacking, defaults to 1 (optional)
  - j index of the last element to unpack, defaults to `t.n` or else `#t` (optional)

  ### Returns:

  multiple return values from the table

  ### See also:

  - compat.unpack
  - utils.pack
  - utils.npairs

  ### Usage:

      local t = table.pack(nil, nil, nil, 4)
      local a, b, c, d = table.unpack(t)   -- this unpack is NOT nil-safe, so d == nil

      local a, b, c, d = utils.unpack(t)   -- this is nil-safe, so d == 4

printf (fmt, ...)
  print an arbitrary number of arguments using a format. Output will be sent to `stdout`.

  ### Parameters:

  - fmt The format (see string.format)
  - ... Extra arguments for format
fprintf (f, fmt, ...)
  write an arbitrary number of arguments to a file using a format.

  ### Parameters:

  - f File handle to write to.
  - fmt The format (see string.format).
  - ... Extra arguments for format
import (t, T)
  take a table and 'inject' it into the local namespace.

  ### Parameters:

  - t The table (table), or module name (string), defaults to this utils module table
  - T An optional destination table (defaults to callers environment)
choose (cond, value1, value2)
  return either of two values, depending on a condition.

  ### Parameters:

  - cond A condition
  - value1 Value returned if cond is truthy
  - value2 Value returned if cond is falsy
array_tostring (t[, temp[, tostr]])
  convert an array of values to strings.

  ### Parameters:

  - t a list-like table
  - temp (table) buffer to use, otherwise allocate (optional)
  - tostr custom tostring function, called with (value,index). Defaults to tostring. (optional)

  ### Returns:

  the converted buffer
is_type (obj, tp)
  is the object of the specified type? If the type is a string, then use type, otherwise compare with metatable

  ### Parameters:

  - obj An object to check
  - tp String of what type it should be

  ### Returns:

  boolean

  ### Usage:

      utils.is_type("hello world", "string")   --> true
      -- or check metatable
      local my_mt = {}
      local my_obj = setmetatable(my_obj, my_mt)
      utils.is_type(my_obj, my_mt)  --> true

npairs (t[, i_start=1[, i_end=t.n or #t[, step=1]]])
  an iterator with indices, similar to ipairs, but with a range. This is a nil-safe index based iterator that will return `nil` when there is a hole in a list. To be safe ensure that table `t.n` contains the length.

  ### Parameters:

  - t table the table to iterate over
  - i_start integer start index (default 1)
  - i_end integer end index (default t.n or #t)
  - step integer step size (default 1)

  ### Returns:

  1. integer index
  2. any value at index (which can be `nil`!)

  ### See also:

  - utils.pack
  - utils.unpack

  ### Usage:

      local t = utils.pack(nil, 123, nil)  -- adds an n field when packing

      for i, v in utils.npairs(t, 2) do  -- start at index 2
        t[i] = tostring(t[i])
      end

      -- t = { n = 3, [2] = "123", [3] = "nil" }

kpairs (t)
  an iterator over all non-integer keys (inverse of ipairs). It will skip any key that is an integer number, so negative indices or an array with holes will not return those either (so it returns slightly less than 'the inverse of ipairs').

  This uses pairs under the hood, so any value that is iterable using pairs will work with this function.

  ### Parameters:

  - t table the table to iterate over

  ### Returns:

  1. key
  2. value

  ### Usage:

      local t = {
        "hello",
        "world",
        hello = "hallo",
        world = "Welt",
      }

      for k, v in utils.kpairs(t) do
        print("German: ", v)
      end

      -- output;
      -- German: hallo
      -- German: Welt

## Tables

patterns
  Some standard patterns

  ### Fields:

  - FLOAT floating point number
  - INTEGER integer number
  - IDEN identifier
  - FILE file
stdmt
  Standard meta-tables as used by other Penlight modules

  ### Fields:

  - List the List metatable
  - Map the Map metatable
  - Set the Set metatable
  - MultiMap the MultiMap metatable

## Error handling

assert_arg (n, val, tp, verify, msg, lev)
  assert that the given argument is in fact of the correct type.

  ### Parameters:

  - n argument index
  - val the value
  - tp the type
  - verify an optional verification function
  - msg an optional custom message
  - lev optional stack position for trace, default 2

  ### Returns:

  the validated value

  ### Raises:

  if `val` is not the correct type

  ### Usage:

      local param1 = assert_arg(1,"hello",'table')  --> error: argument 1 expected a 'table', got a 'string'
      local param4 = assert_arg(4,'!@#$%^&*','string',path.isdir,'not a directory')
           --> error: argument 4: '!@#$%^&*' not a directory

enum (...)
  creates an Enum or constants lookup table for improved error handling. This helps prevent magic strings in code by throwing errors for accessing non-existing values, and/or converting strings/identifiers to other values.

  Calling on the object does the same, but returns a soft error; `nil + err`, if the call is successful (the key exists), it will return the value.

  When calling with varargs or an array the values will be equal to the keys. The enum object is read-only.

  ### Parameters:

  - ... table or vararg the input for the Enum. If varargs or an array then the values in the Enum will be equal to the names (must be strings), if a hash-table then values remain (any type), and the keys must be strings.

  ### Returns:

  Enum object (read-only table/object)

  ### Usage:

  -     -- Enum access at runtime
        local obj = {}
        obj.MOVEMENT = utils.enum("FORWARD", "REVERSE", "LEFT", "RIGHT")

        if current_movement == obj.MOVEMENT.FORWARD then
          -- do something

        elseif current_movement == obj.MOVEMENT.REVERES then
          -- throws error due to typo 'REVERES', so a silent mistake becomes a hard error
          -- "'REVERES' is not a valid value (expected one of: 'FORWARD', 'REVERSE', 'LEFT', 'RIGHT')"

        end

  -     -- standardized error codes
        local obj = {
          ERR = utils.enum {
            NOT_FOUND = "the item was not found",
            OUT_OF_BOUNDS = "the index is outside the allowed range"
          },

          some_method = function(self)
            return nil, self.ERR.OUT_OF_BOUNDS
          end,
        }

        local result, err = obj:some_method()
        if not result then
          if err == obj.ERR.NOT_FOUND then
            -- check on error code, not magic strings

          else
            -- return the error description, contained in the constant
            return nil, "error: "..err  -- "error: the index is outside the allowed range"
          end
        end

  -     -- validating/converting user-input
        local color = "purple"
        local ansi_colors = utils.enum {
          black     = 30,
          red       = 31,
          green     = 32,
        }
        local color_code, err = ansi_colors(color) -- calling on the object, returns the value from the enum
        if not color_code then
          print("bad 'color', " .. err)
          -- "bad 'color', 'purple' is not a valid value (expected one of: 'black', 'red', 'green')"
          os.exit(1)
        end

function_arg (idx, f, msg)
  process a function argument. This is used throughout Penlight and defines what is meant by a function: Something that is callable, or an operator string as defined by `pl.operator`, such as '>' or '#'. If a function factory has been registered for the type, it will be called to get the function.

  ### Parameters:

  - idx argument index
  - f a function, operator string, or callable object
  - msg optional error message

  ### Returns:

  a callable

  ### Raises:

  if idx is not a number or if f is not callable
assert_string (n, val)
  assert the common case that the argument is a string.

  ### Parameters:

  - n argument index
  - val a value that must be a string

  ### Returns:

  the validated value

  ### Raises:

  val must be a string

  ### Usage:

      local val = 42
      local param2 = utils.assert_string(2, val) --> error: argument 2 expected a 'string', got a 'number'

on_error (mode)

  control the error strategy used by Penlight. This is a global setting that controls how utils.raise behaves:

  - 'default': return `nil + error` (this is the default)
  - 'error': throw a Lua error
  - 'quit': exit the program

  ### Parameters:

  - mode either 'default', 'quit' or 'error'

  ### See also:

  utils.raise
raise (err)
  used by Penlight functions to return errors. Its global behaviour is controlled by utils.on_error. To use this function you MUST use it in conjunction with `return`, since it might return `nil + error`.

  ### Parameters:

  - err the error string.

  ### See also:

  utils.on_error

  ### Usage:

      if some_condition then
        return utils.raise("some condition was not met")  -- MUST use 'return'!
      end

## File handling

readfile (filename, is_bin)
  return the contents of a file as a string

  ### Parameters:

  - filename The file path
  - is_bin open in binary mode

  ### Returns:

  file contents
writefile (filename, str, is_bin)
  write a string to a file

  ### Parameters:

  - filename The file path
  - str The string
  - is_bin open in binary mode

  ### Returns:

  1. true or nil
  2. error message

  ### Raises:

  error if filename or str aren't strings
readlines (filename)
  return the contents of a file as a list of lines

  ### Parameters:

  - filename The file path

  ### Returns:

  file contents as a table

  ### Raises:

  error if filename is not a string

## OS functions

executeex (cmd, bin)
  execute a shell command and return the output. This function redirects the output to tempfiles and returns the content of those files.

  ### Parameters:

  - cmd a shell command
  - bin boolean, if true, read output as binary file

  ### Returns:

  1. true if successful
  2. actual return code
  3. stdout output (string)
  4. errout output (string)
quote_arg (argument)
  Quote and escape an argument of a command. Quotes a single (or list of) argument(s) of a command to be passed to os.execute, `pl.utils.execute` or pl.utils.executeex.

  ### Parameters:

  - argument (string or table/list) the argument to quote. If a list then all arguments in the list will be returned as a single string quoted.

  ### Returns:

  quoted and escaped argument.

  ### Usage:

      local options = utils.quote_arg {
          "-lluacov",
          "-e",
          "utils = print(require('pl.utils')._VERSION",
      }
      -- returns: -lluacov -e 'utils = print(require('\''pl.utils'\'')._VERSION'

quit ([code], msg, ...)
  error out of this program gracefully.

  ### Parameters:

  - code The exit code, defaults to -`1` if omitted (optional)
  - msg The exit message will be sent to `stderr` (will be formatted with the extra parameters)
  - ... extra arguments for message's format'

  ### See also:

  utils.fprintf

  ### Usage:

      utils.quit(-1, "Error '%s' happened", "42")
      -- is equivalent to
      utils.quit("Error '%s' happened", "42")  --> Error '42' happened

## String functions

escape (s)
  escape any Lua 'magic' characters in a string

  ### Parameters:

  - s The input string
split (s, re, plain, n)
  split a string into a list of strings separated by a delimiter.

  ### Parameters:

  - s The input string
  - re optional A Lua string pattern; defaults to '%s+'
  - plain optional If truthy don't use Lua patterns
  - n optional maximum number of elements (if there are more, the last will remain un-split)

  ### Returns:

  a list-like table

  ### Raises:

  error if s is not a string

  ### See also:

  splitv
splitv (s, re, plain, n)
  split a string into a number of return values. Identical to split but returns multiple sub-strings instead of a single list of sub-strings.

  ### Parameters:

  - s the string
  - re A Lua string pattern; defaults to '%s+'
  - plain don't use Lua patterns
  - n optional maximum number of splits

  ### Returns:

  n values

  ### See also:

  split

  ### Usage:

      first,next = splitv('user=jane=doe','=', false, 2)
      assert(first == "user")
      assert(next == "jane=doe")

## Functional

memoize (func)
  'memoize' a function (cache returned value for next call). This is useful if you have a function which is relatively expensive, but you don't know in advance what values will be required, so building a table upfront is wasteful/impossible.

  ### Parameters:

  - func a function that takes exactly one argument (which later serves as the cache key) and returns a single value

  ### Returns:

  a function taking one argument and returning a single value either from the cache or by running the original input function
add_function_factory (mt, fun)
  associate a function factory with a type. A function factory takes an object of the given type and returns a function for evaluating it

  ### Parameters:

  - mt table metatable
  - fun function a callable that returns a function
string_lambda (lf)
  an anonymous function as a string. This string is either of the form '|args| expression' or is a function of one argument, '_'

  ### Parameters:

  - lf function as a string

  ### Returns:

  a function

  ### Usage:

      string_lambda '|x|x+1' (2) == 3
      string_lambda '_+1' (2) == 3

bind1 (fn, p)
  bind the first argument of the function to a value.

  ### Parameters:

  - fn a function of at least two values (may be an operator string)
  - p a value

  ### Returns:

  a function such that f(x) is fn(p,x)

  ### Raises:

  same as function_arg

  ### See also:

  func.bind1

  ### Usage:

      local function f(msg, name)
        print(msg .. " " .. name)
      end

      local hello = utils.bind1(f, "Hello")

      print(hello("world"))     --> "Hello world"
      print(hello("sunshine"))  --> "Hello sunshine"

bind2 (fn, p)
  bind the second argument of the function to a value.

  ### Parameters:

  - fn a function of at least two values (may be an operator string)
  - p a value

  ### Returns:

  a function such that f(x) is fn(x,p)

  ### Raises:

  same as function_arg

  ### Usage:

      local function f(a, b, c)
        print(a .. " " .. b .. " " .. c)
      end

      local hello = utils.bind1(f, "world")

      print(hello("Hello", "!"))  --> "Hello world !"
      print(hello("Bye", "?"))    --> "Bye world ?"

## Deprecation

set_deprecation_func (func)
  Sets a deprecation warning function. An application can override this function to support proper output of deprecation warnings. The warnings can be generated from libraries or functions by calling utils.raise_deprecation. The default function will write to the 'warn' system (introduced in Lua 5.4, or the compatibility function from the compat module for earlier versions).

  Note: only applications should set/change this function, libraries should not.

  ### Parameters:

  - func a callback with signature: `function(msg, trace)` both arguments are strings, the latter being optional.

  ### See also:

  utils.raise_deprecation

  ### Usage:

      -- write to the Nginx logs with OpenResty
      utils.set_deprecation_func(function(msg, trace)
        ngx.log(ngx.WARN, msg, (trace and (" " .. trace) or nil))
      end)

      -- disable deprecation warnings
      utils.set_deprecation_func()

raise_deprecation (opts)
  raises a deprecation warning. For options see the usage example below.

  Note: the `opts.deprecated_after` field is the last version in which a feature or option was NOT YET deprecated! Because when writing the code it is quite often not known in what version the code will land. But the last released version is usually known.

  ### Parameters:

  - opts options table

  ### See also:

  utils.set_deprecation_func

  ### Usage:

      warn("@on")   -- enable Lua warnings, they are usually off by default

      function stringx.islower(str)
        raise_deprecation {
          source = "Penlight " .. utils._VERSION,                   -- optional
          message = "function 'islower' was renamed to 'is_lower'", -- required
          version_removed = "2.0.0",                                -- optional
          deprecated_after = "1.2.3",                               -- optional
          no_trace = true,                                          -- optional
        }
        return stringx.is_lower(str)
      end
      -- output: "[Penlight 1.9.2] function 'islower' was renamed to 'is_lower' (deprecated after 1.2.3, scheduled for removal in 2.0.0)"

generated by LDoc 1.5.0