@@ -15,6 +15,9 @@ use log::Log;
1515
1616use crate :: { log_impl, Filter , FormatCallback , Formatter } ;
1717
18+ #[ cfg( feature = "colored" ) ]
19+ use crate :: colors:: ColoredLevelConfig ;
20+
1821#[ cfg( feature = "date-based" ) ]
1922use crate :: log_impl:: DateBasedState ;
2023
@@ -1230,3 +1233,129 @@ impl From<DateBased> for Output {
12301233 } ) ) )
12311234 }
12321235}
1236+
1237+ /// A generic formatter that easily provides good defaults while being configurable
1238+ pub struct FormatterBuilder {
1239+ #[ cfg( feature = "colored" ) ]
1240+ color_config : Option < ColoredLevelConfig > ,
1241+ #[ cfg( feature = "chrono" ) ]
1242+ chrono : bool ,
1243+ level : bool ,
1244+ target : bool ,
1245+ }
1246+
1247+ impl Default for FormatterBuilder {
1248+ fn default ( ) -> Self {
1249+ FormatterBuilder {
1250+ #[ cfg( feature = "colored" ) ]
1251+ color_config : Some ( Default :: default ( ) ) ,
1252+ #[ cfg( feature = "chrono" ) ]
1253+ chrono : true ,
1254+ level : true ,
1255+ target : true ,
1256+ }
1257+ }
1258+ }
1259+
1260+ impl FormatterBuilder {
1261+ pub fn new ( ) -> Self {
1262+ Self :: default ( )
1263+ }
1264+
1265+ pub fn level ( mut self , level : bool ) -> Self {
1266+ self . level = level;
1267+ self
1268+ }
1269+
1270+ pub fn target ( mut self , target : bool ) -> Self {
1271+ self . target = target;
1272+ self
1273+ }
1274+
1275+ #[ cfg( feature = "colored" ) ]
1276+ pub fn color ( mut self , color : bool ) -> Self {
1277+ self . color_config = if color {
1278+ self . color_config . or_else ( Default :: default)
1279+ } else {
1280+ None
1281+ } ;
1282+ self
1283+ }
1284+
1285+ #[ cfg( feature = "colored" ) ]
1286+ pub fn color_config (
1287+ mut self ,
1288+ modify_config : impl FnOnce ( ColoredLevelConfig ) -> ColoredLevelConfig ,
1289+ ) -> Self {
1290+ self . color_config = self . color_config . map ( modify_config) ;
1291+ self
1292+ }
1293+
1294+ #[ cfg( feature = "chrono" ) ]
1295+ pub fn chrono ( mut self , chrono : bool ) -> Self {
1296+ self . chrono = chrono;
1297+ self
1298+ }
1299+
1300+ #[ rustfmt:: skip]
1301+ pub fn build (
1302+ self ,
1303+ ) -> impl Fn ( FormatCallback < ' _ > , & std:: fmt:: Arguments < ' _ > , & log:: Record < ' _ > ) + Sync + Send + ' static
1304+ {
1305+ move |out, message, record| {
1306+ let time = {
1307+ #[ cfg( feature = "chrono" ) ]
1308+ {
1309+ self . chrono
1310+ . then ( || chrono:: Local :: now ( ) . format ( "%Y-%m-%d %H:%M:%S,%3f" ) )
1311+ }
1312+ #[ cfg( not( feature = "chrono" ) ) ]
1313+ {
1314+ None
1315+ }
1316+ } ;
1317+
1318+ let level = if self . level {
1319+ #[ cfg( feature = "colored" ) ]
1320+ {
1321+ Some (
1322+ self . color_config
1323+ . map ( |config| config. color ( record. level ( ) ) )
1324+ . unwrap_or_else ( || crate :: colors:: WithFgColor {
1325+ text : record. level ( ) ,
1326+ color : None ,
1327+ } ) ,
1328+ )
1329+ }
1330+ #[ cfg( not( feature = "colored" ) ) ]
1331+ {
1332+ Some ( record. level ( ) )
1333+ }
1334+ } else {
1335+ None
1336+ } ;
1337+
1338+ let target = self . target . then ( || {
1339+ if !record. target ( ) . is_empty ( ) {
1340+ record. target ( )
1341+ } else {
1342+ record. module_path ( ) . unwrap_or_default ( )
1343+ }
1344+ } ) ;
1345+
1346+ /* Sadly we cannot store and compose std::fmt::Arguments due to lifetime issues.
1347+ * In order to avoid unnecessary write calls nevertheless, we must enumerate all options
1348+ */
1349+ match ( time, level, target) {
1350+ ( Some ( time) , Some ( level) , Some ( target) ) => out. finish ( format_args ! ( "{} {:<5} [{}] {}" , time, level, target, message) ) ,
1351+ ( Some ( time) , Some ( level) , None ) => out. finish ( format_args ! ( "{} {:<5} {}" , time, level, message) ) ,
1352+ ( Some ( time) , None , Some ( target) ) => out. finish ( format_args ! ( "{} [{}] {}" , time, target, message) ) ,
1353+ ( Some ( time) , None , None ) => out. finish ( format_args ! ( "{} {}" , time, message) ) ,
1354+ ( None , Some ( level) , Some ( target) ) => out. finish ( format_args ! ( "{:<5} [{}] {}" , level, target, message) ) ,
1355+ ( None , None , Some ( target) ) => out. finish ( format_args ! ( "[{}] {}" , target, message) ) ,
1356+ ( None , Some ( level) , None ) => out. finish ( format_args ! ( "{:<5} {}" , level, message) ) ,
1357+ ( None , None , None ) => out. finish ( format_args ! ( "{}" , message) ) ,
1358+ }
1359+ }
1360+ }
1361+ }
0 commit comments