A few recipes and starting blueprints for using More
.
Note. Some of the code snippets here assume they are done after:
open More
You can use the spawn tracing facility. At initialization time a tracer that logs spawns on level Debug
is installed. So setting your level to Debug
will trace the process spawns on stderr
.
If you want them to be traced at another level use More.Os.Cmd.spawn_tracer_log
. For example this traces process spawns at the More.Log.level.Stderr
level:
let main () =
Os.Cmd.set_spawn_tracer (Os.Cmd.spawn_tracer_log Stderr);
…
ANSI text styling is controlled globally on all formatters by the More.Fmt.set_styler
function. The initial value depends on a bunch of conditions which are documented here. Text styling can be selectively stripped on strings and formatters with the More.String.strip_ansi_escapes
and More.Fmt.strip_styles
functions.
If you are using Cmdliner
the recommended way to let users control ANSI text styling is to use the More_cli.set_no_color
term which sets the styler by side side effect. The term allows to set the styler to Plain
with the --no-color
command line flag or the NO_COLOR
environment variable (which also happens at initialization time). See More_cli.no_color
for more information and this blueprint for an example.
We advise against changing the styler according to Unix.isatty
. Think about your outputs as being styled text rather than plain text. Users often pipe styled text and and expect it to survive. For example when they page your outputs or redirect messages to a log file. This doesn't mean that you should not support a --no-color
option; only that Unix.isatty
should not be used as signifier for plain text.
The log level is controlled by the More.Log.set_level
function. The initial value is More.Log.level.Warning
.
If you are using Cmdliner
the recommended way to let users control the log level is to use the More_cli.set_log_level
term which sets the log level by side effect. The term allows to set the log level with the --log-level
command line option and a few other flags or the LOG_LEVEL
environment variable. See More_cli.log_level
for more information and this blueprint for an example.
Simply wrap the body of your main
function by a call to More.Log.time
. The call respects the reporting level even if changed in the wrapped function itself. See this this blueprint for an example.
It depends.
The More.Log
module has two specific levels before Quiet
that allow to directly output to stdout
and stderr
by using More.Log.stdout
and More.Log.stderr
.
Using these functions is useful to flush newline ended messages on standard outputs without them being prefixed by the executable name or a log level header and retain the ability to suppress these messages when the reporting level is set to More.Log.level.Quiet
.
Now if you are writing data on your standard output, you should likely not use More.Log.stdout
. This will prevent it from being output when More.Log.level.Quiet
is set which the user may request to silence other diagnostics message.
This blueprint setups ANSI text styling and the log level by side effect. It also reports the total time taken by the tool when the log level is set to Info
.
open More
let tool () =
Log.stdout (fun m -> m "Invoke with %a to silence me" Fmt.code "--quiet");
Cmdliner.Cmd.Exit.ok
open Cmdliner
open Cmdliner.Term.Syntax
let tool_cmd =
Cmd.make (Cmd.info "TODO" ~version:"%%VERSION%%") @@
let+ () = More_cli.set_no_color () in
let+ () = More_cli.set_log_level () in
tool ()
let main () =
Log.time (fun _ m -> m "total time %%VERSION%%") @@ fun () ->
Cmd.eval' tool_cmd
let () = if !Sys.interactive then () else exit (main ())