Module Prelude.Message

Easy to use message functions for warnings, errors, and verbosity, with a lot of fiddly options.

Tutorial

In simplest form, message is just like Printf.eprintf except that it prefixes argv0 to the output.

warning and fatal are like message except they add the word "warning" or "FATAL" (respectively) to the prefix, and fatal also terminates execution (with exit status 1 (by default)).

syntax is for generating syntax error messages with a filename and line number in the usual Unix format understood by editors like Emacs and Vim.

verbose, wrap and maybe are for generating progress messages at varying levels of verbosity.

Examples

Here we assume that (hd argv = "a.out").

See message below for a million optional parameters.

Destinations

val of_chan : Stdlib.out_channel -> Format.formatter
val null : Format.formatter

null is the /dev/null of destinations; setting ~ff:null results in no message being printed.

val myself : string Option.t Stdlib.ref

myself is the program name: the default value for message's ~myself parameter.

The default is (Filename.basename argv0 |> some).

Setting myself to None results in no program name prefix; setting it to (Some p) changes the program name to p.

val sep : string

sep is the default string (": ") used to separate all the components of the message.

val message : ?myself:string -> ?sep:string -> ?quote:(string -> string) -> ?nl:bool -> ?exit:int -> ?prefix:string -> ?flush:bool -> ?ff:Format.formatter -> ('a, unit, string, unit) Stdlib.format4 -> 'a

(message ~ff fmt ARGS ...) formats and prints a message as for (Format.fprintf ff fmt ARGS ...), with behavior modified by the many optional arguments.

(let fn = "foo" in message "%s: file not found" fn) 

prints "test: foo: file not found", assuming (!myself = Some "test").

~ff is the Format.formatter that the message is printed on; the default is Format.err_formatter

If ~myself:m is provided, it overrides myself for this call and uses m for the program name; passing ~myself:"" results in no program name prefix at all.

The printed result is composed of the following elements, in this order, separated by the value of ~sep; elemants that are None are elided:

  • ~myself
  • ~prefix
  • the value of (Format.sprintf fmt ARGS ...)

If ~quote is given, it is applied to each of these elements before the message is assembled. This is expected to be used to quote instances of ~sep to assure that the message text is parseable, but the function can do anything you like.

In any case, if ~nl:true (the default), a terminating end-of-line string as appended to the formatted message, and if ~flush:true (the default), the message is flushed.

If ~exit:status is provided, then the program is terminated by calling (Stdlib.exit status) after the message is printed.

Examples, assuming argv0 returns "test":

  • (message "starting up") prints "test: starting up"
  • (message ~prefix:"INFO" "starting up") prints "test: INFO: starting up"
  • (message ~myself:None "starting up") prints "starting up"
  • (message ~myself:None ~prefix:"INFO" "starting up") prints "INFO: starting up"
  • (message ~myself:"production" "starting up") prints "production: starting up"
val warning : ?myself:string -> ?sep:string -> ?quote:(string -> string) -> ?nl:bool -> ?exit:int -> ?prefix:string -> ?flush:bool -> ?ff:Format.formatter -> ('a, unit, string, unit) Stdlib.format4 -> 'a

(warning fmt ARGS ...) calls message, setting ~prefix:"warning"; all of message's optional arguments supported.

val syntax : ?myself:'a -> ?sep:string -> ?quote:(string -> string) -> ?nl:bool -> ?exit:int -> ?flush:bool -> ?ff:Format.formatter -> string -> int -> ('b, unit, string, unit) Stdlib.format4 -> 'b

(syntax fn ln fmt) is (message ~prefix:(("%s:%d" % fn) ln) fmt).

All of messages's other optional parameters are accepted.

val fatal : ?myself:string -> ?sep:string -> ?quote:(string -> string) -> ?nl:bool -> ?exit:int -> ?prefix:string -> ?flush:bool -> ?ff:Format.formatter -> ('b, unit, string, unit) Stdlib.format4 -> 'b

(fatal fmt ARGS ...) calls message, setting ~prefix:"FATAL" and ~exit:1 (thus terminating the program); all of message's optiional arguments supported.

Verbose Messages

val verbosity : int Stdlib.ref

verbosity determines the level of messages printed by verbose when ~verbosity:default_verbosity (the default).

The initial verbosity level is 0; you can set it or change it:

Message.verbosity := 10
incr Message.verbosity
decr Message.verbosity
val verbose : ?myself:string -> ?sep:string -> ?quote:(string -> string) -> ?prefix:string -> ?nl:bool -> ?flush:bool -> ?exit:int -> ?verbosity:(unit -> int) -> ?ff:Format.formatter -> int -> ('a, unit, string, unit) Stdlib.format4 -> 'a

(verbose ?verbosity level fmt ARGS ...) calls (message fmt ARGS) (passing all optional parameters) but only if the current verbosity is >= level. All of message's optiional arguments are also supported.

~verbosity is called to determine the current verbosity level; the default value is default_verbosity, which fetches the current value of the ref verbosity. See Predefined Verbosity Functions for some convenient functions.

val wrap : ?myself:string -> ?sep:string -> ?quote:(string -> string) -> ?prefix:string -> ?nl:bool -> ?flush:bool -> ?exit:int -> ?verbosity:(unit -> int) -> ?ff:Format.formatter -> ?after:('a -> string) -> int -> string -> ('b -> 'a) -> 'b -> 'a

(wrap ?after level msg f x) returns (f x), wrapping the evaluation in two calls to verbose but only if the current verbosity is >= level. All of verbose's optiional arguments are also supported.

(wrap level "%s" msg f x) is equivalent to:

verbose ~nl:false ~flush:true level "%s" msg;
let result = f x in
verbose ~myself:"" ~nl:true ~flush:true level "%s" Option.(default (k "done") after result);
result 

Both calls pass along all other optional parameters.

The default value for ~after is k "done".

val maybe : ?myself:string -> ?sep:string -> ?quote:(string -> string) -> ?nl:bool -> ?exit:int -> ?flush:bool -> ?verbosity:(unit -> int) -> ?ff:Format.formatter -> bool -> int -> ('a, unit, string, unit) Stdlib.format4 -> 'a

(maybe notreally lvl fmt) is (verbose lvl fmt) unless (notreally = true), in which case it is (verbose ~prefix:"NOT" lvl fmt).

All of verbose's other optional parameters are accepted.

Many of my programs take a -n option meaning to not really do anything destructive. Some variable, say notreally, is set to true when this option is set. Now I can write destructive functions like so:

let makefile notreally fn =
  Message.maybe notreally 1 "creating file %s" fn;
  if notreally
  then ()
  else writefile ~fn "hello, world"

which is silent unless !Message.verbosity is >= 1, in which case we have:

# makefile true "/tmp/nr";;
ocaml: NOT: creating file /tmp/nr
- : unit = ()
# makefile false"/tmp/nr";;
ocaml: creating file /tmp/nr
- : unit = ()
#
val debugging : bool Stdlib.ref
val debug : ?myself:string -> ?sep:string -> ?quote:(string -> string) -> ?nl:bool -> ?exit:int -> ?prefix:string -> ?flush:bool -> ?ff:Format.formatter -> ('a, unit, string, unit) Stdlib.format4 -> 'a

Predefined Verbosity Functions

Suitable for verbose's ~verbosity parameter.

val of_ref : 'a Stdlib.ref -> unit -> 'a

(of_ref r) returns a function that uses ref r to define the verbosity level.

val default_verbosity : unit -> int

(default_verbosity) uses ref verbosity to define the verbosity level.

val env : string -> unit -> int

(env v) returns a function that uses the value of environment variable v (after conversion to an int) to define the verbosity level.

val zero : unit -> int

zero is the constant verbosity level of 0.

val one : unit -> int

one is the constant verbosity level of 1.