Page
Library
Module
Module type
Parameter
Class
Class type
Source
Err
SourceErr is an abstraction to report located errors and warnings to the user.
The canonical syntax for an error produced by this lib is:
File "my-file", line 42, character 6-11:
42 | Hello World
^^^^^
Error: Some message that gives a general explanation of the issue.
Followed by more details.
It is heavily inspired by dune's user_messages and uses dune's error message rendering under the hood.
A value of type t
is an immutable piece of information that the programmer intends to report to the user, in a way that breaks flow. To give some concrete examples:
The exception that is raised to break the control flow of programs using Err
.
Examples:
When reporting an error:
if had_error then Err.raise [ Pp.text "An error occurred" ]
When requesting an exit code:
if shall_exit_42 then Err.exit 42
The standard usage for this library is to wrap entire sections in a protect
, which takes care of catching E
and handling it accordingly. You may also catch this exception manually if you need, for more advanced uses (in which case you'll take care of recording and re-raising backtraces, etc).
Return a Sexp
to inspect what inside t
. Note the sexp is incomplete and it is not meant for supporting any kind of round trip serialization (there is no t_of_sexp
). Rather, this is for quick inspection of what's inside t
. We think exposing this can help accommodating some use cases, making it easier to write expect tests involving Err
, etc.
This part allows breaking the control flow with an exception indicating a request to end the program with a given exit code.
Request the termination of the program with the provided exit code. Make sure you have documented that particular exit code in the man page of your CLI. We recommend to stick to the error codes exposed by Exit_code
, which are documented by default and pervasively used by existing CLIs built with cmdliner. Raises E
.
val raise :
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
Pp_tty.t list ->
_
Raise a user error. You may override exit_code
with the requested exit code to end the program with. It defaults to Exit_code.some_error
.
Example:
let unknown_var var =
Err.raise
~loc
[ Pp.textf "Unknown variable '%s'" var ]
~hints:(Err.did_you_mean var ~candidates:[ "foo"; "bar"; "baz" ])
;;
val reraise :
Printexc.raw_backtrace ->
t ->
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
Pp_tty.t list ->
_
Reraise with added context. Usage:
match do_x (Y.to_x y) with
| exception Err.E e ->
let bt = Printexc.get_raw_backtrace () in
Err.reraise bt e [ Pp.text "Trying to do x with y"; Y.pp y ]
val create :
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
Pp_tty.t list ->
t
Create a err and return it, instead of raising it right away.
append ?exit_code t1 t2
creates a new err that contains all messages of t1 and t2. The exit_code of this new t
may be specified, otherwise it will be that of t2
.
This is exposed to help with libraries compatibility if needed.
Helper to raise a user error from a result type.
ok_exn (Ok x)
is x
ok_exn (Error msg)
is Stdlib.raise (E msg)
Whether that is during a migration, or to keep experimenting, we are currently exploring other ways to build and raise errors, using things like sexp, json or dyn.
val create_s :
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
string ->
Sexplib0.Sexp.t ->
t
val raise_s :
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
string ->
Sexplib0.Sexp.t ->
_
val reraise_s :
Printexc.raw_backtrace ->
t ->
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
string ->
Sexplib0.Sexp.t ->
_
Reraise with added context. Usage:
match do_x x with
| exception Err.E e ->
let bt = Printexc.get_raw_backtrace () in
Err.reraise_s bt e "Trying to do x with y" [%sexp { y : Y.t }]
When you need to render a Sexp.t
into a _ Pp.t
paragraph, things may become tricky - newlines inserted in surprising places, etc. This functions attempts to do an OK job at it.
Produces a "Did you mean ...?" hint
Set by the For_test.wrap
when wrapping sections for tests, accessed by libraries if needed.
This return the number of errors that have been emitted via Err.error
since the last reset_counts
. Beware, note that errors raised as exceptions via functions such as Err.raise
do not affect the error count. The motivation is to allow exceptions to be caught without impacting the overall exit code.
A convenient wrapper for Err.error_count () > 0
.
This is useful if you are trying not to stop at the first error encountered, but still want to stop the execution at a specific breakpoint after some numbers of errors. To be used in places where you want to stop the flow at a given point rather than returning meaningless data.
Return the number of warnings that have been emitted via Err.warning
since the last reset_counts
.
Inspired by the git diff --color=<WHEN>
command line parameter, this library allows to access the rendering mode that should be used to style the output aimed for the user, in the terminal or perhaps using a pager.
If you use Log_cli.set_config
, your cli will also support the same --color
flag as git diff
. You can access the value that was set via the color_mode
getter. The default mode is `Auto
.
Even though it is traditionally called "color"-mode, this goes beyond simply colors and controls all forms of style rendering construct, such as bold, italic, and other ansi special characters.
Inspired by logging conventions in many CLI tools, this library provides a mechanism to control the verbosity of log messages based on their severity level. This allows users to filter messages, ensuring that only relevant information is displayed during program execution.
The log level can be set programmatically or via command-line flags using Log_cli
. The default log level is Warning
, meaning only warnings and errors will be displayed unless a more verbose level is explicitly set.
The available log levels are:
Quiet
: Suppresses all log messages, including errors.Error
: Displays only error messages.Warning
: Displays warnings and errors (default).Info
: Displays informational messages, warnings, and errors.Debug
: Displays all messages, including debug information.Programs can query the current log level using log_level
and check whether a specific level is enabled using log_enables
. This is useful for conditionally executing code that should only run at certain verbosity levels.
Example usage:
if Err.log_enables Debug
then (
(* Perform expensive debugging operations *)
let debug_data = compute_debug_data () in
Err.debug (lazy [ Pp.textf "Debug data: %s" debug_data ]))
Note: Functions such as Err.info
, Err.warning
, and Err.debug
automatically check the log level before emitting messages. You do not need to call log_enables
before using them.
When using Log_cli
, the log level can be set via a command-line flag (e.g., --verbosity=debug
). This ensures consistent behavior across applications using this library.
Note: A level named App
has been added to ensure compatibility with the Logs
library, as this constructor is part of Logs.level
. However, this module does not differentiate between the Quiet
and App
levels. The App
level is primarily included to facilitate interoperability with third-party libraries that rely on Logs
.
Access the current log level.
Tell whether the current log level enables the output of messages of the supplied level.
Print to stderr
(not thread safe). By default, prerr
will start by writing a blank line on stderr
if Err
messages have already been emitted during the lifetime of the program. That is a reasonable default to ensure that err messages are always nicely separated by an empty line, to make them more readable. However, if you structure your output manually, perhaps you do not want this. If reset_separator=true
, this behavior is turned off, and the first message of this batch will be printed directly without a leading blank line.
This part of the library allows the production of messages that do not raise.
For example: - Emitting multiple errors before terminating - Non fatal Warnings - Debug and Info messages
Errors and warnings are going to affect error_count
(and resp. warning_count
), which is going to be used by protect
to impact the exit code of the application. Use with care.
Emit an error on stderr and increase the global error count.
Emit a warning on stderr and increase the global warning count.
Emit a information message on stderr. Required verbosity level of Info
or more, disabled by default.
The last argument to debug
is lazy in order to avoid the allocation when debug messages are disabled. This isn't done with the other functions, because we don't expect other logging functions to be used in a way that impacts the program's performance, and using lazy causes added programming friction.
To be used by command line handlers, as well as tests.
protect f
will take care of running f
, and catch any user error. If the exit code must be affected it is returned as an Error
. This also takes care of catching uncaught exceptions and printing them to the screen. You may provide exn_handler
to match on custom exceptions and turn them into Err
for display and exit code. Any uncaught exception will be reported as an internal errors with a backtrace. When Err.am_running_test ()
is true the backtrace is redacted to avoid making expect test traces too brittle. protect
starts by performing a reset of the error and warning counts with a call to reset_counts
.