Skip to content

Conversation

@CodeZea1ot
Copy link
Contributor

Closes #434

Changes

  • Adds a new gum tail subcommand
  • Allows user to stream stdin for -n number of lines
  • Keeps logs from piped running processes from cluttering up the terminal

Example

{ sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y; } | gum tail -n 3 // Stream the last 3 lines of info generated by this process until complete

@CodeZea1ot CodeZea1ot requested a review from maaslalani as a code owner April 22, 2024 21:00
@maaslalani
Copy link
Contributor

maaslalani commented Apr 22, 2024

Hey @CodeZea1ot, thanks so much for the contribution!

What benefit do you get with gum tail vs simply using tail?

@CodeZea1ot
Copy link
Contributor Author

Hey there @maaslalani

The idea behind a gum tail is to be able to stream output from a long running process that produces a lot of output with a configurable amount of visible max lines.

For example, say you have a script that runs an install or download process that you don't want to hide with gum spin, you could instead show the last -n lines of the output to the user, with it refreshing until the process ends.

In other words, you would get up to -n lines of output at all times and those lines that are displayed would always show the latest lines from the piped command coming into stdin.

Recording.2024-04-22.181848.mp4

@newcron
Copy link

newcron commented Apr 26, 2024

I have to say, that's one of the features I'm waiting for so that I can start to use it.

My usecase is a local dev environment in which several automated steps are performed to simplify the dev process.

in my case, I would love exactly that for my build script, which should: build the code, create a test environment (databases with fixtures,...), then start the application and then run the end to end tests.

Each of these steps produces output, which I don't want the whole screen to pollute. at the same time, it would be very useful for the developers to get a glimpse on what's going on (e.g. if there is an error in the build, or the application crashes at startup).

Filling the whole screen with that just feels too verbose, yet not showing at all leaves the user without any sense of real progress.

@CodeZea1ot
Copy link
Contributor Author

I built a BASH CLI called spyglass for this use case. You can check it out over at https://github.com/CodeZea1ot/spyglass

This is the functionality I'd like to bring to a gum tail command.

main_demo

Copy link
Member

@caarlos0 caarlos0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made some suggestions

also would be good to run goimports/gofmt

gum.go Outdated
Comment on lines 200 to 201
// Tail
// Provides a means of streaming -n of lines from stdin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Tail
// Provides a means of streaming -n of lines from stdin
// Tail provides a means of streaming a number of lines from stdin.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change applied in 0087173

gum.go Outdated

// Tail
// Provides a means of streaming -n of lines from stdin
// Useful for showing a subset of output from a process without clogging up the terminal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Useful for showing a subset of output from a process without clogging up the terminal
// It is useful for showing a subset of output from a process without clogging up the terminal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change applied in 0087173

// Provides a means of streaming -n of lines from stdin
// Useful for showing a subset of output from a process without clogging up the terminal
//
// $ { sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y; } | gum tail -n 3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// $ { sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y; } | gum tail -n 3
// Let's watch apt update:
//
// $ { sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y; } | gum tail -n 3

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change applied in 0087173

tail/command.go Outdated
"os"
)

// Run executes the tail command
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Run executes the tail command
// Run executes the tail command.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change applied in 0087173

tail/command.go Outdated
}

func clearScreen() {
fmt.Print("\033[H\033[2J")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fmt.Print("\033[H\033[2J")
fmt.Print(ansi.EraseDisplay(2))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tail/command.go Outdated
Comment on lines 55 to 61
start := len(lines) - n
if start < 0 {
start = 0
}
for i := start; i < len(lines); i++ {
fmt.Println(lines[i])
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
start := len(lines) - n
if start < 0 {
start = 0
}
for i := start; i < len(lines); i++ {
fmt.Println(lines[i])
}
fmt.Println(strings.Join(lines, "\n"))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored in 45e1406

See following comment #544 (comment)

tail/command.go Outdated
// Continuously read lines from stdin and update the last n lines
for line := range lines {
lastLines = appendLine(lastLines, line, o.NumLines)
clearScreen()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❔ Can we put clearScreen() behind an option?

I'd prefer the behaviour shown in #434.1967362421, i.e. gum tail would leave the screen content "above" alone, and only update its "own" N lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this refactor solves the clear screen problem and improves the functionality of the tail command.

45e1406

Screencast.from.09-11-2025.10.36.47.AM.webm

@reitzig
Copy link

reitzig commented Sep 10, 2025

Is there anything beyond above comments by @caarlos0 preventing this from being merged?

@CodeZea1ot CodeZea1ot requested a review from a team as a code owner September 11, 2025 13:30
@CodeZea1ot CodeZea1ot requested review from andreynering and meowgorithm and removed request for a team and maaslalani September 11, 2025 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add command to tail n lines of output

5 participants