Prelude.MessageEasy to use message functions for warnings, errors, and verbosity, with a lot of fiddly options.
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.
Here we assume that (hd argv = "a.out").
(message "%d + %d = %d" 2 4 (2+4)) --stderr--> "a.out: 2 + 4 = 6"(warning "%d + %d <> %d" 2 4 100) --stderr--> "a.out: warning: 2 + 4 <> 100"(fatal "out of stuff!") --stderr--> "a.out: FATAL: out of stuff!" and Sys.exit 1(let fn,ln = "z.ml",134 in syntax fn ln "syntax error!") --stderr--> "z.ml:134:syntax error!"(verbosity := 0; verbose 1 "something computed") no output(verbosity := 1; verbose 1 "something computed") --stderr--> "a.out: something computed"(verbosity := 2; verbose 1 "something computed") --stderr--> "a.out: something computed"(verbosity := 1; verbose 2 "something computed") no output(verbosity := 1; wrap 1 "sleeping... " Unix.sleep 3) --stderr--> "a.out: sleeping... " (after 3 seconds...) "done"See message below for a million optional parameters.
val of_chan : Stdlib.out_channel -> Format.formatterof_chan is Format.formatter_of_out_channel.
val null : Format.formatternull is the /dev/null of destinations; setting ~ff:null results in no message being printed.
val myself : string Option.t Stdlib.refmyself 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.
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(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 ->
'aval 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 ->
'bverbosity 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.verbosityval 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 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 ->
'aSuitable for verbose's ~verbosity parameter.
(of_ref r) returns a function that uses ref r to define the verbosity level.
(default_verbosity) uses ref verbosity to define the verbosity level.
(env v) returns a function that uses the value of environment variable v (after conversion to an int) to define the verbosity level.