Class Models for Lua

# Verbose Manager

## `loop.debug.Verbose`

Class of objects that provide operations to generate and manage verbose messages of a continuous application. All messages are flagged and may be hierarchly organized in order to reflect the application structure. The flagged messages can be turned on/off by flag or group of flags. The messages also provides support for indentation in order to reflect the hierarchical structure of the calls of functions of the application. This class is useful for implementation of logging mechanisms in server applications.

Each object can be indexed to provide a method to be used to generate verbose messages. The name of the method is the flag of the message produced. The methods provided accept an abritrary number of values that are written to the output if the message flag is active. Optionally, these methods also receive a `boolean` as the first parameter that indicates if the indentation level should be increased (`true`) or decreased (`false`).

## Behavior

### Initialization

`Verbose([object])`
  Turns `object` into an instance of `Verbose` and sets the values of its fields if they are not already set. If `object` is not provided a new table is created to represent the object. Anyway, the new created instance is returned.

### Fields

`groups`
  Field that holds a table that map the name of a group of flags to a list of the flags belonging tho that group. It also maps the number of a given verbose level to the list of flags introduced at that level. This table should be accessed through metods `addgroup`, `newlevel` and `setlevel`.
`custom`
  Field that holds a table that map the name of a flag to a function used to generate a custom message from the parameters passed to the method used to generate the message. The custom function receives as arguments the `Verbose` instance (i.e. like an ordinary method) and all the values passed to the method called to generate the message. The custom function is responsible to write the message using the `viewer` field. Additionally, the custom function may cancel the message customization by returning some value (that evaluates to `true`), in such case the message is produced as if no custom function were defined.
`inspect`
  Field that holds a table that map the name of a flag or group of flags to a function that is called after each message of that flag is generated. Typically, this is used to introduce a pause at each message of a given flag. Optionally, this field may be set to a function, in such case, this function is used for all flagged messages generated through that instance. If the value set for a given flag or group of flags or even all flags (i.e. by setting the value of the field itself) is the value `true` then the function `io.read()` is used to introduce a pause at the end of each message generation.
`timed`
  Field that holds a table that map the name of a flag or group of flags to a string used as a parameter to the function `os.date()` to generate a timestamp for each generated message of that flag. Optionally, this field may be set to a string, in such case, this string is used for all flagged messages generated through that instance. If the value set for a given flag or group of flags or even all flags (i.e. by setting the value of the field itself) is the value `true` then default format of function `os.date()` is used to create a timestamp for the messages.
`viewer`
  Field that holds the object used to print out messages of the command prompt. The object must provide the same API of instances of `Viewer`. The default value for this field is an instance of `Viewer` with `maxdepth` set to 2.

### Methods

`flag(name [, status])`
  If `status` is `true`, the flag or group of flags `name` is activated and all further messages generated with that flag will be printed. If `status` is `false`, the flag or group of flags `name` is deactivated and all calls to the method used to generate messages with that flag (i.e. method with the same name of the flag) are ignored. If `status` is not provided, the call returns `true` if the flag is currently activated or `false` otherwise.
`level([value])`
  If `value` is provided then this value is set as the current verbose level in such way that all flags from the same level or lower are active and flags of levels higher than `level` are inactive. Otherwise, the current verbose level is returned.
`newlevel([level, ] group)`
  Inserts the list of flags `group` in the verbose level `level` shifting all upper levels. If no `level` is provided the group is added to the higher level available. Therefore, when the verbose level is set to a level equal or greater than `level`, these flags will be active.
`setgroup(name, group)`
  Defines that the list of flags `group` compose the group of flags `name`. Therefore, whenever the status of flag `name` is changed, all the flags of the group are changed to the same status.
`setlevel(level, group)`
  Defines that the list of flags `group` defines the set of flags added at level `group`.

### Meta-Fields

`__index = function`
  Retrieves methods used to print messages with the index string as flag. The methods provided receive an arbitrary number of arguments that are written to the output to generate messages. Strings have their contents written directly to the output while other values have their textual representation generated by field `viewer` written to the output. If the first argument is a boolean value, then the indentation level of all generated messages is increased (`true`) or decreased (`false`).

## Remarks

- The following flags are reserved for the internal implementation of the `Verbose` class:
  - `custom`
  - `flag`
  - `flags`
  - `groups`
  - `inspect`
  - `level`
  - `newlevel`
  - `setgroup`
  - `setlevel`
  - `timed`
  - `updatetabs`

## Examples

### Counter that generates a log of its actions.

    local Verbose = require "loop.debug.Verbose"

    LOG = Verbose{
      groups = {
        -- levels
        {"main"},
        {"counter"},
        -- aliases
        all = {"main", "counter"},
      },
    }
    LOG:flag("all", true)

    local oo = require "loop.base"

    local Counter = oo.class{
      value = 0,
      step = 1,
    }
    function Counter:add()                LOG:counter "Adding step to counter"
      self.value = self.value + self.step
    end

    counter = Counter()                   LOG:main "Counter object created"
    steps = 10                            LOG:main(true, "Counting ",steps," steps")
    for i=1, steps do counter:add() end   LOG:main(false, "Done! Counter=",counter)

Copyright (C) 2004-2008 Tecgraf, PUC-Rio

This project is currently being maintained by Tecgraf at PUC-Rio.