@@ -6,13 +6,23 @@ import (
66 "io"
77 "log/slog"
88 "strconv"
9+ "strings"
910 "sync"
1011 "sync/atomic"
1112 "time"
1213 "unicode"
1314 "unicode/utf8"
1415)
1516
17+ const (
18+ resetSeq = "0"
19+ boldSeq = "1"
20+ faintSeq = "2"
21+
22+ esc = '\x1b'
23+ csi = string (esc ) + "["
24+ )
25+
1626// HandlerOption is the signature of a functional option that can be used to
1727// modify the behaviour of the DefaultHandler.
1828type HandlerOption func (* handlerOpts )
@@ -49,6 +59,15 @@ func WithCallerFlags(flags uint32) HandlerOption {
4959 }
5060}
5161
62+ // WithStyledOutput can be used to add additional styling to the logs. This
63+ // currently includes colored & bold tags and faint fonts for attribute keys and
64+ // callsites.
65+ func WithStyledOutput () HandlerOption {
66+ return func (opts * handlerOpts ) {
67+ opts .styled = true
68+ }
69+ }
70+
5271// WithNoTimestamp is an option that can be used to omit timestamps from the log
5372// lines.
5473func WithNoTimestamp () HandlerOption {
@@ -228,6 +247,23 @@ func (d *DefaultHandler) with(tag string, withCallstackOffset bool,
228247 return & sl
229248}
230249
250+ func (d * DefaultHandler ) styleString (s string , styles ... string ) string {
251+ if ! d .opts .styled {
252+ return s
253+ }
254+
255+ if len (styles ) == 0 {
256+ return s
257+ }
258+
259+ seq := strings .Join (styles , ";" )
260+ if seq == "" {
261+ return s
262+ }
263+
264+ return fmt .Sprintf ("%s%sm%s%sm" , csi , seq , s , csi + resetSeq )
265+ }
266+
231267func (d * DefaultHandler ) appendAttr (buf * buffer , a slog.Attr ) {
232268 // Resolve the Attr's value before doing anything else.
233269 a .Value = a .Value .Resolve ()
@@ -244,15 +280,19 @@ func (d *DefaultHandler) appendAttr(buf *buffer, a slog.Attr) {
244280func (d * DefaultHandler ) writeLevel (buf * buffer , level Level ) {
245281 str := fmt .Sprintf ("[%s]" , level )
246282
247- buf .writeString (str )
283+ buf .writeString (d .styleString (
284+ str , boldSeq , string (level .ansiColoSeq ())),
285+ )
248286}
249287
250288func (d * DefaultHandler ) writeCallSite (buf * buffer , file string , line int ) {
251289 if file == "" {
252290 return
253291 }
254292
255- buf .writeString (fmt .Sprintf (" %s:%d" , file , line ))
293+ buf .writeString (
294+ d .styleString (fmt .Sprintf (" %s:%d" , file , line ), faintSeq ),
295+ )
256296}
257297
258298func appendString (buf * buffer , str string ) {
@@ -270,7 +310,7 @@ func (d *DefaultHandler) appendKey(buf *buffer, key string) {
270310 }
271311 key += "="
272312
273- buf .writeString (key )
313+ buf .writeString (d . styleString ( key , faintSeq ) )
274314}
275315
276316func appendValue (buf * buffer , v slog.Value ) {
0 commit comments