From a319a85de8864a4d2a2f8b00ba67bc706a1a6b6a Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Mon, 16 Sep 2024 14:22:53 -0400 Subject: [PATCH] gopls/internal/telemetry/cmd/stacks: display closed issues white The isTerminal implementation works for our dev machines, {darwin,linux} x {amd64,arm}, and avoids a dependency on x/term, which gopls so far doesn't need... though I am now tempted to find a pretext for the dependency. Change-Id: If96b5cf737c9ea998d0612dec294295a5528b22a Reviewed-on: https://go-review.googlesource.com/c/tools/+/613575 Reviewed-by: Robert Findley Auto-Submit: Alan Donovan LUCI-TryBot-Result: Go LUCI --- gopls/internal/telemetry/cmd/stacks/stacks.go | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/gopls/internal/telemetry/cmd/stacks/stacks.go b/gopls/internal/telemetry/cmd/stacks/stacks.go index a0d9b3c30..746b0ff68 100644 --- a/gopls/internal/telemetry/cmd/stacks/stacks.go +++ b/gopls/internal/telemetry/cmd/stacks/stacks.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux || darwin + // The stacks command finds all gopls stack traces reported by // telemetry in the past 7 days, and reports their associated GitHub // issue, creating new issues as needed. @@ -73,12 +75,14 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "sort" "strconv" "strings" "time" "unicode" + "golang.org/x/sys/unix" "golang.org/x/telemetry" "golang.org/x/tools/gopls/internal/util/browser" "golang.org/x/tools/gopls/internal/util/moremaps" @@ -410,6 +414,12 @@ func main() { fmt.Printf("%s issues:\n", caption) for _, summary := range keys { count := issues[summary] + // Show closed issues in "white". + if isTerminal(os.Stdout) && strings.Contains(summary, "[closed]") { + // ESC + "[" + n + "m" => change color to n + // (37 = white, 0 = default) + summary = "\x1B[37m" + summary + "\x1B[0m" + } fmt.Printf("%s (n=%d)\n", summary, count) } } @@ -940,3 +950,21 @@ func findPredicateBlock(body string) string { } return rest } + +// isTerminal reports whether file is a terminal, +// avoiding a dependency on golang.org/x/term. +func isTerminal(file *os.File) bool { + // Hardwire the constants to avoid the need for build tags. + // The values here are good for our dev machines. + switch runtime.GOOS { + case "darwin": + const TIOCGETA = 0x40487413 // from unix.TIOCGETA + _, err := unix.IoctlGetTermios(int(file.Fd()), TIOCGETA) + return err == nil + case "linux": + const TCGETS = 0x5401 // from unix.TCGETS + _, err := unix.IoctlGetTermios(int(file.Fd()), TCGETS) + return err == nil + } + panic("unreachable") +}