diff --git a/README.md b/README.md
index 639ab28..ef0ee3e 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,14 @@ Clutchlog — versatile (de)clutchable logging
- [Project page on Github](https://github.com/nojhan/clutchlog)
- [Documentation](https://nojhan.github.io/clutchlog/)
-
+
+
+
+
[TOC]
Features
@@ -77,23 +84,6 @@ API documentation
=================
-Log level semantics
--------------------
-
-Log levels use a classical semantics for a human skilled in the art, in decreasing order of importance:
-
-- *Critical*: an error that cannot be recovered. For instance, something which will make a server stop right here.
-- *Error*: an error that invalidates a function, but may still be recovered. For example, a bad user input that will make a server reset its state, but not crash.
-- *Warning*: something that is strange, but is probably legit. For example a default parameter is set because the user forgot to indicate its preference.
-- *Progress*: the state at which computation currently is.
-- *Note*: some state worth noting to understand what's going on.
-- *Info*: any information that would help ensuring that everything is going well.
-- *Debug*: data that would help debugging the program if there was a bug later on.
-- *XDebug*: debugging information that would be heavy to read.
-
-Note: the log levels constants are lower case (for example: `clutchlog::level::xdebug`), but their string representation is not (e.g. "XDebug", this should be taken into account when using `threshold` or `level_of`).
-
-
Calls
-----
@@ -128,6 +118,23 @@ CLUTCHDUMP(debug, vec, "test_{n}.dat");
Note that if you pass a file name without the `{n}` tag, the file will be overwritten as is.
+Log level semantics
+-------------------
+
+Log levels use a classical semantics for a human skilled in the art, in decreasing order of importance:
+
+- *Critical*: an error that cannot be recovered. For instance, something which will make a server stop right here.
+- *Error*: an error that invalidates a function, but may still be recovered. For example, a bad user input that will make a server reset its state, but not crash.
+- *Warning*: something that is strange, but is probably legit. For example a default parameter is set because the user forgot to indicate its preference.
+- *Progress*: the state at which computation currently is.
+- *Note*: some state worth noting to understand what's going on.
+- *Info*: any information that would help ensuring that everything is going well.
+- *Debug*: data that would help debugging the program if there was a bug later on.
+- *XDebug*: debugging information that would be heavy to read.
+
+Note: the log levels constants are lower case (for example: `clutchlog::level::xdebug`), but their string representation is not (e.g. "XDebug", this should be taken into account when using `threshold` or `level_of`).
+
+
Location filtering
------------------
@@ -234,7 +241,16 @@ and its default with the `CLUTCHLOG_DEFAULT_HFILL_MARK` macro:
log.hfill_mark(CLUTCHLOG_DEFAULT_HFILL_MARK); // Defaults to '.'.
```
-Note: if the system detects no terminal, only a single fill character is inserted.
+Clutchlog measures the width of the standard error channel.
+If it is redirected, it may be measured as very large.
+Thus, the `hfill_max` accessors allow to set a maximum width (in number of characters).
+```cpp
+log.hfill_max(CLUTCHLOG_DEFAULT_HFILL_MAX); // Defaults to 300.
+```
+Note: clutchlog will select the minimum between `hfill_max`
+and the measured number of columns in the terminal,
+so that you may use `hfill_max` as a way to constraint the output width
+in any cases.
## Stack Depth
@@ -306,6 +322,12 @@ log.format(format.str());
Note: messages at the "critical", "error" and "warning" log levels are colored by default.
You may want to set their style to `none` if you want to stay in control of inserted colors in the format template.
+The horizontal filling line (the `{hfill}` tag) can be configured separately with `hfill_style`,
+for example:
+```cpp
+ log.hfill_style(clutchlog::fmt::fg::black);
+```
+
Disabled calls
--------------
@@ -318,7 +340,7 @@ by setting the `WITH_CLUTCHLOG` preprocessor variable.
When the `NDEBUG` preprocessor variable is set (e.g. in `Release` build),
clutchlog will do its best to allow the compiler to optimize out any calls
-for log levels that are under or equal to `progress`.
+for log levels that are under `progress`.
You can change this behavior at compile time by setting the
`CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG` preprocessor variable
diff --git a/clutchlog/clutchlog.h b/clutchlog/clutchlog.h
index 134792a..ac3b639 100644
--- a/clutchlog/clutchlog.h
+++ b/clutchlog/clutchlog.h
@@ -1,6 +1,6 @@
-#ifndef __CLUTCHLOG_H__
-#define __CLUTCHLOG_H__
#pragma once
+#ifndef CLUTCHLOG_H
+#define CLUTCHLOG_H
/** @file */
#include
@@ -257,10 +257,23 @@ class clutchlog
#endif // CLUTCHLOG_HFILL_MARK
//! Default character used as a filling for right-align the right part of messages with "{hfill}".
static inline char default_hfill_char = CLUTCHLOG_HFILL_MARK;
+
+
+ #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
+ #ifndef CLUTCHLOG_HFILL_MAX
+ #define CLUTCHLOG_HFILL_MAX 300
+ #endif
+ #endif
+ //! Default maximum number of character used as a filling for right-align the right part of messages with "{hfill}".
+ static inline unsigned short default_hfill_max = CLUTCHLOG_HFILL_MAX;
+
+ // NOTE: there is no CLUTCHLOG_HFILL_STYLE for defaulting,
+ // but you can still set `hfill_style(...)` on the logger singleton.
/* @} */
public:
+
/** @name High-level API
* @{ */
@@ -435,12 +448,16 @@ class clutchlog
}),
_format_log(clutchlog::default_format),
_format_dump(clutchlog::dump_default_format),
- _hfill_char(clutchlog::default_hfill_char),
+ #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
+ _hfill_char(clutchlog::default_hfill_char),
+ _hfill_fmt(fmt::fg::none),
+ _hfill_max(clutchlog::default_hfill_max),
+ #endif
_out(&std::clog),
-#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
- _depth(std::numeric_limits::max() - _strip_calls),
- _depth_mark(clutchlog::default_depth_mark),
-#endif
+ #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
+ _depth(std::numeric_limits::max() - _strip_calls),
+ _depth_mark(clutchlog::default_depth_mark),
+ #endif
_stage(level::error),
_in_file(".*"),
_in_func(".*"),
@@ -452,8 +469,8 @@ class clutchlog
}
#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
struct winsize w;
- ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
- _nb_columns = w.ws_col;
+ ioctl(STDERR_FILENO, TIOCGWINSZ, &w);
+ _nb_columns = std::min(w.ws_col, default_hfill_max);
#endif
}
@@ -470,16 +487,22 @@ class clutchlog
std::string _format_log;
/** Current format of the file output. */
std::string _format_dump;
- /** Character for filling. */
- char _hfill_char;
+ #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
+ /** Character for filling. */
+ char _hfill_char;
+ /** Style of the filling. */
+ fmt _hfill_fmt;
+ /** Maximum number of fill char. */
+ unsigned short _hfill_max;
+ #endif
/** Standard output. */
std::ostream* _out;
-#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
- /** Current stack depth (above which logs are not printed). */
- size_t _depth;
- /** Current depth mark. */
- std::string _depth_mark;
-#endif
+ #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
+ /** Current stack depth (above which logs are not printed). */
+ size_t _depth;
+ /** Current depth mark. */
+ std::string _depth_mark;
+ #endif
/** Current log level. */
level _stage;
/** Current file location filter. */
@@ -541,6 +564,20 @@ class clutchlog
void hfill_mark(const char mark) {_hfill_char = mark;}
//! Get the character for the stretching hfill marker.
char hfill_mark() const {return _hfill_char;}
+ //! Set the style for the stretching hfill marker, with a `fmt` object.
+ void hfill_style(fmt style) {_hfill_fmt = style;}
+ /** Set the style for the stretching hfill marker.
+ *
+ * This version accept style arguments as if they were passed to `clutchlog::fmt`.
+ */
+ template
+ void style(FMT... styles) { this->hfill_style(fmt(styles...)); }
+ //! Get the character for the stretching hfill marker.
+ fmt hfill_style() const {return _hfill_fmt;}
+ //! Set the maximum number of hfill characters. */
+ void hfill_max(const size_t nmax) {_hfill_max = nmax;}
+ //! Get the maximum number of hfill characters. */
+ unsigned short hfill_max() {return _hfill_max;}
#endif
//! Set the log level (below which logs are not printed) with an identifier.
@@ -800,15 +837,19 @@ class clutchlog
if(right_len+left_len > _nb_columns) {
// The right part would go over the terminal width: add a new line.
const std::string hfill(std::max((size_t)0, _nb_columns-right_len), _hfill_char);
- format = replace(format, "\\{hfill\\}", "\n"+hfill);
+ const std::string hfill_styled = _hfill_fmt(hfill);
+ format = replace(format, "\\{hfill\\}", "\n"+hfill_styled);
} else {
// There is some space in between left and right parts.
const std::string hfill(std::max((size_t)0, _nb_columns - (right_len+left_len)), _hfill_char);
- format = replace(format, "\\{hfill\\}", hfill);
+ const std::string hfill_styled = _hfill_fmt(hfill);
+ format = replace(format, "\\{hfill\\}", hfill_styled);
}
} else {
// We don't know the terminal width.
- format = replace(format, "\\{hfill\\}", _hfill_char);
+ const std::string hfill(1, _hfill_char);
+ const std::string hfill_styled = _hfill_fmt(hfill);
+ format = replace(format, "\\{hfill\\}", hfill_styled);
}
}
#endif
@@ -967,12 +1008,16 @@ class clutchlog
#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
void hfill_mark(const char) {}
char hfill_mark() const {}
+ void hfill_fmt(fmt) {}
+ fmt hfill_fmt() const {}
+ void hfill_max(const size_t) {}
+ unsigned short hfill_max() {}
#endif
void threshold(level) {}
void threshold(const std::string&) {}
level threshold() const {}
- const std::map levels() const {};
+ const std::map levels() const {}
level level_of(const std::string) {}
void file(std::string) {}
@@ -988,6 +1033,8 @@ class clutchlog
)
{}
#pragma GCC diagnostic pop
+ template
+ void style(level, FMT...) {}
void style(level, fmt) {}
fmt style(level) const {}
public:
@@ -1042,4 +1089,4 @@ class clutchlog
#pragma GCC diagnostic pop
#endif // WITH_CLUTCHLOG
-#endif // __CLUTCHLOG_H__
+#endif // CLUTCHLOG_H