@@ -6,12 +6,22 @@ import (
66 "io"
77 "log/slog"
88 "strconv"
9+ "strings"
910 "sync"
1011 "sync/atomic"
1112 "unicode"
1213 "unicode/utf8"
1314)
1415
16+ const (
17+ resetSeq = "0"
18+ boldSeq = "1"
19+ faintSeq = "2"
20+
21+ esc = '\x1b'
22+ csi = string (esc ) + "["
23+ )
24+
1525// HandlerOption is the signature of a functional option that can be used to
1626// modify the behaviour of the DefaultHandler.
1727type HandlerOption func (* handlerOpts )
@@ -39,6 +49,15 @@ func WithCallerFlags(flags uint32) HandlerOption {
3949 }
4050}
4151
52+ // WithStyledOutput can be used to add additional styling to the logs. This
53+ // currently includes colored & bold tags and faint fonts for attribute keys and
54+ // callsites.
55+ func WithStyledOutput () HandlerOption {
56+ return func (opts * handlerOpts ) {
57+ opts .styled = true
58+ }
59+ }
60+
4261// WithNoTimestamp is an option that can be used to omit timestamps from the log
4362// lines.
4463func WithNoTimestamp () HandlerOption {
@@ -211,6 +230,23 @@ func (d *DefaultHandler) with(tag string, withCallstackOffset bool,
211230 return & sl
212231}
213232
233+ func (d * DefaultHandler ) styleString (s string , styles ... string ) string {
234+ if ! d .opts .styled {
235+ return s
236+ }
237+
238+ if len (styles ) == 0 {
239+ return s
240+ }
241+
242+ seq := strings .Join (styles , ";" )
243+ if seq == "" {
244+ return s
245+ }
246+
247+ return fmt .Sprintf ("%s%sm%s%sm" , csi , seq , s , csi + resetSeq )
248+ }
249+
214250func (d * DefaultHandler ) appendAttr (buf * buffer , a slog.Attr ) {
215251 // Resolve the Attr's value before doing anything else.
216252 a .Value = a .Value .Resolve ()
@@ -227,15 +263,19 @@ func (d *DefaultHandler) appendAttr(buf *buffer, a slog.Attr) {
227263func (d * DefaultHandler ) writeLevel (buf * buffer , level Level ) {
228264 str := fmt .Sprintf ("[%s] " , level )
229265
230- buf .writeString (str )
266+ buf .writeString (d .styleString (
267+ str , boldSeq , string (level .ansiColoSeq ())),
268+ )
231269}
232270
233271func (d * DefaultHandler ) writeCallSite (buf * buffer , file string , line int ) {
234272 if file == "" {
235273 return
236274 }
237275
238- buf .writeString (fmt .Sprintf (" %s:%d" , file , line ))
276+ buf .writeString (
277+ d .styleString (fmt .Sprintf (" %s:%d" , file , line ), faintSeq ),
278+ )
239279}
240280
241281func appendString (buf * buffer , str string ) {
@@ -253,7 +293,7 @@ func (d *DefaultHandler) appendKey(buf *buffer, key string) {
253293 }
254294 key += "="
255295
256- buf .writeString (key )
296+ buf .writeString (d . styleString ( key , faintSeq ) )
257297}
258298
259299func appendValue (buf * buffer , v slog.Value ) {
0 commit comments