@@ -42,20 +42,14 @@ pub const Config = struct {
4242 strftime : []const u8 ,
4343 } = .disabled ,
4444 /// Whether to enable color output.
45- color : enum {
46- /// Check for NO_COLOR, CLICOLOR_FORCE and tty support on stderr.
47- /// Color output is disabled on other writers.
48- auto ,
49- /// Enable color output on every writers.
50- always ,
51- /// Disable color output on every writers.
52- never ,
53- } = .auto ,
45+ /// This can be modified at runtime using `updateTtyConfig`.
46+ color : Color = .auto ,
5447 /// Set to `.none` to disable all styles.
5548 styles : Styles = .{},
5649 /// The text to display for each log level.
5750 level_text : LevelText = .{},
5851 /// Whether to write log messages to stderr.
52+ /// This is modifiable at runtime.
5953 quiet : bool = false ,
6054 /// The mutex interface to use for the log messages.
6155 mutex : union (enum ) {
@@ -68,15 +62,13 @@ pub const Config = struct {
6862
6963/// Create a new logger based on the given configuration.
7064pub fn Axe (comptime config : Config ) type {
71- const writers_tty_config : tty.Config = switch (config .color ) {
72- .always = > .escape_codes ,
73- .auto , .never = > .no_color ,
74- };
75-
7665 return struct {
66+ /// Whether to write log messages to stderr.
67+ pub var quiet = config .quiet ;
68+
7769 var writers : []* std.Io.Writer = &.{};
78- // zig/llvm can't handle this without explicit type
79- var stderr_tty_config : if ( config . quiet ) void else tty.Config = if (config .quiet ) {} else .no_color ;
70+ var stderr_tty_config = defaultTtyConfig ( config . color );
71+ var writers_tty_config = defaultTtyConfig (config .color ) ;
8072 var timezone = if (config .time_format != .disabled ) zeit .utc else {};
8173 var mutex = switch (config .mutex ) {
8274 .none , .function = > {},
@@ -111,16 +103,7 @@ pub fn Axe(comptime config: Config) type {
111103 if (additional_writers ) | _writers | {
112104 writers = try allocator .dupe (* std .Io .Writer , _writers );
113105 }
114- if (! config .quiet ) {
115- stderr_tty_config = switch (config .color ) {
116- .auto = > .detect (std .fs .File .stderr ()),
117- .always = > if (builtin .os .tag == .windows ) switch (.detect (std .fs .File .stderr ())) {
118- .no_color , .escape_codes = > .escape_codes ,
119- .windows_api = > | ctx | .{ .windows_api = ctx },
120- } else .escape_codes ,
121- .never = > .no_color ,
122- };
123- }
106+ updateTtyConfig (config .color );
124107 }
125108
126109 /// Deinitialize the logger.
@@ -131,6 +114,22 @@ pub fn Axe(comptime config: Config) type {
131114 allocator .free (writers );
132115 }
133116
117+ /// Update tty configuration for stderr and additional writers.
118+ pub fn updateTtyConfig (color : Color ) void {
119+ writers_tty_config = defaultTtyConfig (color );
120+ stderr_tty_config = switch (color ) {
121+ .auto = > .detect (std .fs .File .stderr ()),
122+ .always = > if (builtin .os .tag == .windows )
123+ switch (tty .Config .detect (std .fs .File .stderr ())) {
124+ .no_color , .escape_codes = > .escape_codes ,
125+ .windows_api = > | ctx | .{ .windows_api = ctx },
126+ }
127+ else
128+ .escape_codes ,
129+ .never = > .no_color ,
130+ };
131+ }
132+
134133 /// Returns a scoped logging namespace that logs all messages using the scope provided.
135134 pub fn scoped (comptime scope : @Type (.enum_literal )) type {
136135 return struct {
@@ -281,7 +280,7 @@ pub fn Axe(comptime config: Config) type {
281280 print (src , writer , writers_tty_config , time , level , scope , format , args );
282281 writer .flush () catch {};
283282 }
284- if (! config . quiet ) {
283+ if (! quiet ) {
285284 var buffer : [256 ]u8 = undefined ;
286285 var stderr = std .fs .File .stderr ().writer (& buffer );
287286 print (src , & stderr .interface , stderr_tty_config , time , level , scope , format , args );
@@ -417,6 +416,7 @@ pub const Style = union(enum) {
417416 bg_rgb : struct { r : u8 , g : u8 , b : u8 },
418417 /// #RRGGBB, #RGB, RRGGBB, RGB
419418 hex : []const u8 ,
419+ /// #RRGGBB, #RGB, RRGGBB, RGB
420420 bg_hex : []const u8 ,
421421
422422 inline fn fmt (comptime styles : []const Style , comptime text : []const u8 ) []const u8 {
@@ -563,6 +563,16 @@ pub const Style = union(enum) {
563563 }
564564};
565565
566+ pub const Color = enum {
567+ /// Check for NO_COLOR, CLICOLOR_FORCE and tty support on stderr.
568+ /// Color output is disabled on other writers.
569+ auto ,
570+ /// Enable color output on every writers.
571+ always ,
572+ /// Disable color output on every writers.
573+ never ,
574+ };
575+
566576pub const Styles = struct {
567577 // levels
568578 err : []const Style = &.{ .bold , .red },
@@ -713,6 +723,13 @@ fn writeLocation(
713723 }
714724}
715725
726+ inline fn defaultTtyConfig (color : Color ) tty.Config {
727+ return switch (color ) {
728+ .always = > .escape_codes ,
729+ .auto , .never = > .no_color ,
730+ };
731+ }
732+
716733test "log without styles" {
717734 const expectEqualStrings = std .testing .expectEqualStrings ;
718735 var buffer : [256 ]u8 = undefined ;
@@ -782,6 +799,7 @@ test "log with complex config" {
782799}
783800
784801test "time format" {
802+ const expectEqual = std .testing .expectEqual ;
785803 var dest : std.Io.Writer.Allocating = .init (std .testing .allocator );
786804 defer dest .deinit ();
787805
@@ -790,7 +808,6 @@ test "time format" {
790808 .scope_format = "|%" ,
791809 .time_format = .{ .strftime = "%Y-%m-%d %H:%M:%S" },
792810 .loc_format = "|%m" ,
793- .quiet = true ,
794811 .color = .never ,
795812 .level_text = .{
796813 .debug = "DBG" ,
@@ -799,20 +816,21 @@ test "time format" {
799816 .err = "ERR" ,
800817 },
801818 });
819+ log .quiet = true ;
802820 try log .init (std .testing .allocator , &.{& dest .writer }, null );
803821 defer log .deinit (std .testing .allocator );
804822
805823 log .info ("Hello {c}" , .{'W' });
806824 // [YYYY-mm-dd HH:MM:SS|INF] Hello W
807- try std . testing . expectEqual (34 , dest .written ().len );
825+ try expectEqual (34 , dest .written ().len );
808826 dest .writer .end = 0 ;
809827 log .scoped (.foo ).warn ("Hi" , .{});
810828 // [YYYY-mm-dd HH:MM:SS|WRN|foo] Hi
811- try std . testing . expectEqual (33 , dest .written ().len );
829+ try expectEqual (33 , dest .written ().len );
812830 dest .writer .end = 0 ;
813831 log .errAt (@src (), "Bye {}" , .{'*' });
814832 // [YYYY-mm-dd HH:MM:SS|ERR|root] Bye 42
815- try std . testing . expectEqual (38 , dest .written ().len );
833+ try expectEqual (38 , dest .written ().len );
816834}
817835
818836test "json log" {
@@ -855,3 +873,29 @@ test "json log" {
855873 \\
856874 , writer .buffered ());
857875}
876+
877+ test "updateTtyConfig" {
878+ const expectEqualStrings = std .testing .expectEqualStrings ;
879+ var buffer : [256 ]u8 = undefined ;
880+ var writer = std .Io .Writer .fixed (& buffer );
881+
882+ const log = Axe (.{
883+ .color = .never ,
884+ .quiet = true ,
885+ });
886+ try log .init (std .testing .allocator , &.{& writer }, null );
887+ defer log .deinit (std .testing .allocator );
888+
889+ log .debug ("No color" , .{});
890+ try expectEqualStrings ("debug: No color\n " , writer .buffered ());
891+ writer .end = 0 ;
892+
893+ log .updateTtyConfig (.always );
894+ log .debug ("With color" , .{});
895+ try expectEqualStrings (Style .fmt (&.{ .bold , .cyan }, "debug" ) ++ ": With color\n " , writer .buffered ());
896+ writer .end = 0 ;
897+
898+ log .updateTtyConfig (.never );
899+ log .debug ("No color again" , .{});
900+ try expectEqualStrings ("debug: No color again\n " , writer .buffered ());
901+ }
0 commit comments