From a6aa63ed1f8cdaa5c6b0cbd2a997356cd3b46a4c Mon Sep 17 00:00:00 2001 From: Bruno Schaatsbergen Date: Mon, 16 Dec 2024 12:42:59 -0800 Subject: [PATCH] Fix flaky tab writing behavior using text/tabwriter (#25) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix flaky tab writing behavior This fixes problems with tab writing caused by using a regular os.File writer. By standardizing the tab writer’s usage and ensuring consistent initialization, we improve the reliability and consistency of output formatting a lot. * view: improve tabwriter documentation * view: add the ability to debug the tabwriter In the past, we’ve faced too many issues with flaky tab formatting. If the `debug` flag is specified, we should enable debugging for the tabwriter as well, leveraging its built-in support for this. * view: move newline handling back to renderer * view: preserve comment --- cmd/root.go | 6 +++--- internal/view/format.go | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 95a506f..a985b03 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,7 +2,6 @@ package cmd import ( "fmt" - "io" "os" "sort" "strings" @@ -74,7 +73,7 @@ var ( vt = arguments.ViewHuman } - var w io.Writer = os.Stdout + var w = view.NewTabWriter(os.Stdout, debug) logFile := os.Getenv("ZNS_LOG_FILE") if logFile != "" { f, err := os.Create(logFile) @@ -82,7 +81,7 @@ var ( panic(fmt.Sprintf("Failed to create log file: %v", err)) } defer f.Close() - w = f + w = view.NewTabWriter(f, debug) } v := view.NewRenderer(vt, &view.View{ @@ -152,6 +151,7 @@ var ( v.Render(args[0], record) } } + w.Flush() // we need to flush the buffer to ensure all data is written to the underlying stream. }, } ) diff --git a/internal/view/format.go b/internal/view/format.go index 5ede329..72c7529 100644 --- a/internal/view/format.go +++ b/internal/view/format.go @@ -2,14 +2,34 @@ package view import ( "fmt" + "io" "strconv" "strings" + "text/tabwriter" "time" "github.com/fatih/color" "github.com/miekg/dns" ) +// NewTabWriter initializes and returns a new tabwriter.Writer. +// ZNS uses this writer to format DNS records into a clear, human-readable table. +// See https://pkg.go.dev/text/tabwriter#Writer.Init for details. +func NewTabWriter(w io.Writer, debug bool) *tabwriter.Writer { + flags := uint(0) + if debug { + flags = tabwriter.Debug + } + return tabwriter.NewWriter( + w, + 0, // Minwidth + 8, // Tabwidth + 3, // Padding + ' ', // Padchar + flags, + ) +} + // formatTTL converts TTL to a more readable format (hours, minutes, seconds). func formatTTL(ttl uint32) string { duration := time.Duration(ttl) * time.Second @@ -89,8 +109,8 @@ func formatRecord(domainName string, answer dns.RR) string { Unknown record type: %s We encountered an unsupported DNS record type: %s. -Please consider raising an issue on GitHub to add support for this record type. +Please consider raising an issue on GitHub to add support for this record type. https://github.com/znscli/zns/issues/new Thank you for your contribution!