Goto Chapter: Top 1 2 3 4 5 Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

4 Progress Printer
 4.1 Terminal
 4.2 Block
 4.3 Pattern
 4.4 Layout
 4.5 Printer Module
 4.6 Implementation
 4.7 Process
 4.8 Example

4 Progress Printer

Here we include a guide how to modify the progress printing. This chapter is intended for advanced users or developers of the package.

The progress printer is a framework built from a collection of printer moduls that are solely responsible to display a specific information about the current state of a process e.g. the number of completed iterations or the total runtime. Moreover it specifies an abstract layout e.g. the positional relations between the individual moduls.

In the following we explain the terminology of the framework and the technical implementation. See also Section 2.1 for some basic terminology.

In the end we include an example how to adjust the progress printer.

4.1 Terminal

We can think of the terminal as a finite grid of cells each indexed by an (x, y)-coordinate and assigned a single character. The cursor is an object that occupies the space of exactly one cell. We are able to perform the following actions:

The coordinate (1, 1) denotes the cell in the terminal where the usual Print command would start to write a character, i.e. the initial position of the cursor after hitting the "enter key" on the gap prompt. We think of this cell as the top left corner of the space that we reserve to print the progress. Increasing the x-coordinate can be understood as movement to the right, whereas increasing the y-coordinate as movement to the bottom.

4.2 Block

A block is a virtually allocated space in the terminal (see Section 4.1) in form of a rectangle, a record rec(x, y, w, h), where the top left corner of the interior is the cell at the coordinate (x, y), the width is given by w and the height by h, i.e. the bottom right corner of the interior is the cell at the coordinate (x + w - 1, y + h - 1).

For example we would see something akin to the following if we fill the inside of the block (x := 3, y := 2, w := 5, h := 2) with the symbols "O" and use a simple dot "." for the outside:

..........
..OOOOO...
..OOOOO...
..........
..........

4.3 Pattern

The main purpose of a pattern is to encode a coherent display of the progress. We use patterns to create blocks in a structured and uniform manner of which a few special ones are defining bounds for printer modules. The progress printer has a pattern tree whose nodes are patterns, records that contain the following entries:

id

Unique identifier string of the pattern.

parent

A pattern or fail.

children

List of patterns.

isActive

A function that takes as input a process and returns whether the branch starting in this pattern is active.

alignment

"horizontal" all blocks created from children of this pattern are aligned horizontally, i.e. they have equal y-coordinates and heights.

"vertical" all blocks created from children of this pattern are aligned vertically, i.e. they have equal x-coordinates and widths.

sync

["dim", ...] all blocks created from this pattern have equal values for the dimension dim, etc.

If a pattern is a leaf node, it must additionally contain the following entries:

printer

A printer module.

printer_options

An options record for the printer.

4.3-1 Creating Blocks

For each process we create blocks from the pattern tree using a recursive strategy: If the pattern is active for the given process (pattern.isActive(process) = True), we create a block with the given id (stored in process.blocks.id) and apply the same strategy for all children of the pattern.

A block created from the root of the pattern tree is called a process block. The width of a process block spans the whole terminal screen. Furthermore we require that the process blocks are stacked from top to bottom following the natural ordering of the process tree given by DFS (depth-first search).

A block created from an inner node of the pattern tree is called a composition block. The interior of such a block must be the disjoint union of the interior of its children, and either the children are aligned horizontally within the block, or vertically. Visually speaking, we split a composition block into smaller blocks by either using only vertical or horizontal cuts.

A block created from a leaf node of the pattern tree is called a printer block. This block corresponds to a printer module that is capable of displaying a specific information about the current state of a process inside the block bounds. (See 4.5)

4.4 Layout

The layout is a record containing the following entries:

Setup

A function that setups the following entries of the progress printer using the current options in ProgressPrinter.Options:

DefaultOptions

The default options record for Setup.

4.5 Printer Module

A printer module is responsible for displaying a specific information about the current state of a process e.g. the number of completed iterations or the total runtime. Technically, it is a record that must contain the following functions as entries where the argument options must be valid printer options for this module. For a description of all available printer modules, see Chapter 5.

4.5-1 dimensions
‣ dimensions( process, options )( function )

Returns a dimensions record rec(w, h) where the dimensions are positive integers or fail.

If the values are integers, they specify the smallest dimensions of a block that is capable to display the information about the current state of this process.

A value fail indicates that the dimension is unspecified and can be replaced by any arbitrary positive integer.

4.5-2 generate
‣ generate( process, id, options )( function )

Displays the information of this process in the block with identifier id under the assumption that the block contains no characters and is large enough to display the information.

Therefore the printer usually needs to write characters for most of the interior of the block.

4.5-3 update
‣ update( process, id, options )( function )

Displays the information of this process in the block with identifier id under the assumption that generate was called beforehand and the block bounds haven't changed since then.

Therefore the printer usually just updates a few characters in the terminal.

Returns true if it is capable to display the information in the block, otherwise false.

4.6 Implementation

The progress printer, as described in the introduction of this chapter, is implemented as a record that eventually contains the following entries:

Layout

A record rec(Setup, DefaultOptions) for setting up a layout.

RootProcess

The process tree containing the main process as the root.

Dimensions

A record rec(w, h) encoding the virtual bounds in the terminal.

Cursor

A record rec(x, y) encoding the cursor position.

TimeStamp

An internal time stamp that is changed whenever a process is refreshed.

Options

The current options record for Layout.Setup.

Pattern

The tree consisting of patterns.

InitialConfiguration

A configuration is a list containing entries describing linear equations. These describe additional relations between the blocks created from the patterns of the layout.

An entry is of the form [ factor, rec(id, param), ..., a ] which is interpreted as factor * id.param + ... = a. Here, factor and a must be integers, id the identifier of a pattern in the layout and param a parameter of a block, i.e. either "x", "y", "w" or "h".

CurProcess

The process that is currently running.

4.7 Process

See Section 2.1 for the basic terminology. An abstract process is encoded via a process record, but we usually omit the distinction between them. The record has the following entries:

id

Unique identifier string of the process.

parent

A process record or fail.

children

List of process records.

depth

The depth is a non-negative integer showing how far nested this process is in the root. The root has depth = 0. Any other process has depth = parent.depth + 1.

totalTime

Total runtime of process up to the most recent refresh.

status

The main intent is to mark for the RefreshProcess command how to update the total runtime of a process.

A permanent status is one that can last after a refresh:

"active", "inactive", "complete".

A temporary status is one that transforms immediately into a new one after a refresh:

"started", "stopped", "terminated".

Below is a flow chart showcasing how each status can be transformed into one another, given that doRefresh is true. Therefore we only deal with the commands StartProcess, StopProcess and TerminateProcess for a permanent status. We ommit the arrows for those commands that do not change the status.



           +----------+
+--------> |          |      Refresh
|          | inactive | <--------------+
+----------+          |                |
  Refresh  +----+-----+                |
                |                      |
                | Start                |
                |                      |
                v                      |
           +----------+                |
           |          |                |
           | started  |                |
           |          |                |
           +----+-----+                |
                |                      |
                | Refresh              |
                |                      |
                v                      |
           +----------+          +-----+----+
+--------> |          |  Stop    |          |
|          |  active  +--------> | stopped  |
+----------+          |          |          |
  Refresh  +----+-----+          +----------+
                |
                | Terminate
                |
                v
           +----------+
           |          |
           |terminated|
           |          |
           +----+-----+
                |
                | Refresh
                |
                v
           +----------+
+--------> |          |
|          | complete |
+----------+          |
  Refresh  +----------+


We mention one edge case for completeness. If a process is defined via an iterator that doesn't complete after totalSteps, we change back from the complete status to the active status, and set totalSteps := infinity and blocks := rec().

completedSteps

The number of completed steps of a process. It is initialized with -1. This indicates that the process hasn't started yet.

totalSteps

Number of comleted steps for a process to be marked as terminated.

content

Extra content of the process that may be used by the progress printer or printer modules.

blocks

A record containing entries id := block, where id is a string corresponding to an id in the used pattern, and a block is a record of the form rec(x, y, w, h). A printer block may be popullated with additional entries by the corresponding printer module.

4.8 Example

TODO

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 Ind

generated by GAPDoc2HTML