Module Notty.I

I is for image.

Construction and composition of images.

Consult the basics for an overview.

type t = image
val height : image -> int
val width : image -> int
val equal : t -> t -> bool

equal t1 t2 is true iff t1 and t2 are constructed by the same term.

Note This is a weak form of equality. Images that are not equal could still render the same.

Primitives

val empty : image

empty is a zero-sized image.

val string : attr -> string -> image

string attr s is an image containing text s, styled with attr.

  • raises Invalid_argument

    if string is not a valid UTF-8 sequence, or contains control characters.

val uchars : attr -> Uchar.t array -> image

uchars attr us is an image containing text us, styled with attr.

  • raises Invalid_argument

    if us contains control characters.

val char : attr -> char -> int -> int -> image

char attr c w h is a w * h grid of c.

  • raises Invalid_argument

    if c is a control character.

val uchar : attr -> Uchar.t -> int -> int -> image

uchar attr u w h is a w * h grid of u.

  • raises Invalid_argument

    if u is a control character.

val void : int -> int -> image

void w h is a w * h rectangle of transparent cells.

void is magical: it has geometry, but no displayable content. This is different, for example, from the space character U+0020, which renders as a cell filled with the background color. This means that void interacts specially with overlays.

void 0 0 = empty. void with only one dimension 0 acts as a spacing element in the other dimension. Negative size is treated as 0.

Image composition

Three basic composition modes allow construction of more complex images from simpler ones.

Composition operators are left-associative and form a monoid with void.

val (<|>) : image -> image -> image

i1 <|> i2 is the horizontal combination of i1 and i2.

width (i1 <|> i2) = width i1 + width i2 height (i1 <|> i2) = max (height i1) (height i2)

Images are top-aligned. The missing region is implicitly filled with void.

[x] <|> [y] = [xy]
        [y]   [.y]

where . denotes void.

val (<->) : image -> image -> image

i1 <-> i2 is the vertical combination of i1 and i2.

width (i1 <-> i2) = max (width i1) (width i2) height (i1 <-> i2) = height i1 + height i2

Images are left-aligned. The missing region is implicitly filled with void.

[xx] <-> [y] = [xx]
               [y.]
val (</>) : image -> image -> image

i1 </> i2 is i1 overlaid over i2.

width (i1 </> i2) = max (width i1) (width i2) height (i1 </> i2) = max (height i1) (height i2)

Images are top-left-aligned. In the region of their overlap, only the void cells of i1 show fragments of i2.

[x.x] </> [yyyy] = [xyxy]

Cropping and padding

val hcrop : int -> int -> image -> image

hcrop left right i is i with left leftmost, and right rightmost columns missing. If left + right >= width i the result is empty.

If either left or right is negative, instead of being cropped, the image is padded on that side.

For example:

  • hcrop 0 1 [abc] = [ab]
  • hcrop 1 1 [abc] = [b]
  • hcrop (-1) 1 [abc] = void 1 1 <|> hcrop 0 1 [abc] = [.ab]
  • hcrop 2 2 [abc] = empty
val vcrop : int -> int -> image -> image

vcrop top bottom i is the vertical analogue to hcrop.

val crop : ?l:int -> ?r:int -> ?t:int -> ?b:int -> image -> image

crop ~l:left ~r:right ~t:top ~b:bottom i is vcrop left right (hcrop top bottom) i.

Missing arguments default to 0.

val hpad : int -> int -> image -> image

hcrop with margins negated.

val vpad : int -> int -> image -> image

vcrop with margins negated.

val pad : ?l:int -> ?r:int -> ?t:int -> ?b:int -> image -> image

crop with margins negated.

Additional combinators

val hcat : image list -> image

hcat xs horizontally concatenates xs. See beside.

val vcat : image list -> image

vcat xs vertically concatenates xs. See above.

val zcat : image list -> image

zcat xs overlays xs. See over.

val tabulate : int -> int -> (int -> int -> image) -> image

tabulate m n f is the grid of values f x y with x = 0..m-1 and y = 0..n-1, where x grows to the right, and y growns down.

f a y is to the left of f b y if a < b, and f x a is above f x b if a < b, but the exact alignment is unspecified if the various f x y have different dimensions.

val hsnap : ?align:[ `Left | `Middle | `Right ] -> int -> image -> image

hsnap ~align w i is an image of width strictly w obtained by either horizontally padding or cropping i and positioning it according to ~align.

~align defaults to `Middle.

val vsnap : ?align:[ `Top | `Middle | `Bottom ] -> int -> image -> image

vsnap ~align h i is an image of height strictly h obtained by either vertically padding or cropping i and positioning it according to ~align.

~align defaults to `Middle.

Format interoperability

val strf : ?attr:attr -> ?w:int -> ('aFormat.formatter, unit, image) format4 -> 'a

strf ?attr ?w:width format ... pretty-prints like Format.asprintf format ..., but returns an image.

attr is the (outermost) attribute. Defaults to A.empty.

width is used to set the margin on the formatter. This is only a hint, and does not guarantee the width of the result. Consult Format.set_margin for details. Defaults to an unspecified, large number.

  • raises Invalid_argument

    if the printing process attempts to directly output control characters, by embedding them in format or a string printed with the %s conversion, for example. Formatted printing is allowed.

val kstrf : ?attr:attr -> ?w:int -> (image -> 'a) -> ('bFormat.formatter, unit, 'a) format4 -> 'b

kstrf ?attr ?w k format ... is continuation-based strf ?attr ?w format ....

val pp_attr : attr -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a -> unit

pp_attr a f is a pretty-printer like f, except its output is styled with a. This applies only outside of any styling f itself might embed.