Documentation Index
Fetch the complete documentation index at: https://mintlify.com/raystack/salt/llms.txt
Use this file to discover all available pages before exploring further.
The terminator package provides utilities for terminal detection, pager management, browser launching, and Homebrew integration.
Installation
go get github.com/raystack/salt/cli/terminator
Terminal Detection
TTY Detection
Check if the application is running in a terminal:
import "github.com/raystack/salt/cli/terminator"
if terminator.IsTTY() {
// Running in terminal - can use colors, prompts, etc.
fmt.Println("Running in terminal")
} else {
// Output is redirected or piped - use plain text
fmt.Println("Output redirected")
}
Use Cases
func printOutput(data interface{}) {
if terminator.IsTTY() {
// Interactive terminal - use colors and formatting
printer.PrettyJSON(data)
} else {
// Piped or redirected - use machine-readable format
printer.JSON(data)
}
}
Color Detection
Check if color output is disabled:
if terminator.IsColorDisabled() {
// User set NO_COLOR environment variable
// Use plain text without colors
fmt.Println("Colors disabled")
} else {
// Colors are allowed
printer.Success("Colors enabled")
}
CI Detection
Detect if running in a Continuous Integration environment:
if terminator.IsCI() {
// Running in CI - disable interactive features
fmt.Println("CI environment detected")
// Skip interactive prompts
// Use default values
// Disable spinners and animations
} else {
// Local development - enable interactive features
p := prompter.New()
value, _ := p.Input("Enter value:", "default")
}
Detects these CI environments:
- GitHub Actions
- Travis CI
- CircleCI
- Cirrus CI
- GitLab CI
- AppVeyor
- CodeShip
- Jenkins
- TeamCity
- TaskCluster
Display long output in a paginated format using a pager like less or more.
Basic Usage
import "github.com/raystack/salt/cli/terminator"
pager := terminator.NewPager()
// Start the pager
if err := pager.Start(); err != nil {
log.Fatal(err)
}
defer pager.Stop()
// Write output to pager
fmt.Fprintln(pager.Out, "Line 1")
fmt.Fprintln(pager.Out, "Line 2")
fmt.Fprintln(pager.Out, "Line 3")
// ... many more lines
The pager respects the PAGER environment variable:
# Use less
export PAGER="less"
# Use less with options
export PAGER="less -R"
# Use more
export PAGER="more"
# Disable pager
export PAGER="cat"
pager := terminator.NewPager()
pager.Set("less -R") // Set custom pager command
if err := pager.Start(); err != nil {
log.Fatal(err)
}
defer pager.Stop()
fmt.Fprintln(pager.Out, "Output goes here")
func displayLogs(logs []string) error {
// Only use pager if in TTY
if !terminator.IsTTY() {
for _, log := range logs {
fmt.Println(log)
}
return nil
}
// Use pager for long output
pager := terminator.NewPager()
if err := pager.Start(); err != nil {
return err
}
defer pager.Stop()
for _, log := range logs {
fmt.Fprintln(pager.Out, log)
}
return nil
}
type Pager struct {
Out io.Writer // Writer to send output to pager
ErrOut io.Writer // Writer for error output
}
// Create new pager (uses PAGER env var or "more")
pager := terminator.NewPager()
// Set custom pager command
pager.Set("less -R")
// Get current pager command
cmd := pager.Get()
// Start pager process
err := pager.Start()
// Stop pager process and cleanup
pager.Stop()
Browser Integration
Open URLs in the default web browser.
Basic Usage
import (
"runtime"
"github.com/raystack/salt/cli/terminator"
)
url := "https://example.com"
cmd := terminator.OpenBrowser(runtime.GOOS, url)
if err := cmd.Run(); err != nil {
log.Printf("Failed to open browser: %v", err)
}
func openDocs() error {
if !terminator.IsTTY() {
return fmt.Errorf("cannot open browser: not a TTY")
}
url := "https://docs.example.com"
cmd := terminator.OpenBrowser(runtime.GOOS, url)
return cmd.Run()
}
- macOS: Uses
open command
- Windows: Uses
cmd /c start command
- Linux: Uses
xdg-open or wslview (for WSL)
Non-blocking Browser Launch
func openBrowserAsync(url string) {
cmd := terminator.OpenBrowser(runtime.GOOS, url)
// Start in background
if err := cmd.Start(); err != nil {
log.Printf("Failed to open browser: %v", err)
return
}
// Don't wait for browser to close
go func() {
cmd.Wait()
}()
fmt.Println("Opening browser...")
}
Interactive Browser Prompt
func openDocumentation() error {
url := "https://docs.example.com"
fmt.Printf("Documentation: %s\n", url)
if terminator.IsTTY() {
p := prompter.New()
open, err := p.Confirm("Open in browser?", true)
if err != nil {
return err
}
if open {
cmd := terminator.OpenBrowser(runtime.GOOS, url)
return cmd.Run()
}
}
return nil
}
Homebrew Integration
Utilities for detecting and working with Homebrew on macOS/Linux.
Check Homebrew Installation
if terminator.HasHomebrew() {
fmt.Println("Homebrew is installed")
} else {
fmt.Println("Homebrew is not installed")
}
Check if Binary is from Homebrew
import "os"
func checkInstallation() {
execPath, err := os.Executable()
if err != nil {
log.Fatal(err)
}
if terminator.IsUnderHomebrew(execPath) {
fmt.Println("This tool was installed via Homebrew")
} else {
fmt.Println("This tool was not installed via Homebrew")
}
}
Update Check Example
func checkForUpdates() {
execPath, _ := os.Executable()
if terminator.IsUnderHomebrew(execPath) {
fmt.Println("To update, run: brew upgrade mytool")
} else {
fmt.Println("Download latest version from GitHub releases")
}
}
Complete Example
Here’s a complete example combining multiple terminal utilities:
package main
import (
"fmt"
"log"
"os"
"runtime"
"strings"
"github.com/raystack/salt/cli/printer"
"github.com/raystack/salt/cli/prompter"
"github.com/raystack/salt/cli/terminator"
)
func main() {
// Detect environment
if terminator.IsCI() {
fmt.Println("Running in CI - using defaults")
runNonInteractive()
return
}
if !terminator.IsTTY() {
fmt.Println("Not a TTY - using machine-readable output")
runNonInteractive()
return
}
// Interactive mode
runInteractive()
}
func runInteractive() {
// Check colors
if terminator.IsColorDisabled() {
fmt.Println("Colors disabled by user")
} else {
printer.Boldln("Interactive Mode")
}
// Get logs
logs := generateLogs(100)
// Use pager for long output
if err := displayWithPager(logs); err != nil {
log.Fatal(err)
}
// Offer to open documentation
p := prompter.New()
openDocs, err := p.Confirm("Open documentation?", false)
if err != nil {
log.Fatal(err)
}
if openDocs {
cmd := terminator.OpenBrowser(runtime.GOOS, "https://docs.example.com")
if err := cmd.Run(); err != nil {
printer.Warningf("Failed to open browser: %v\n", err)
}
}
// Check installation method
execPath, _ := os.Executable()
if terminator.IsUnderHomebrew(execPath) {
printer.Infoln("Installed via Homebrew")
printer.Infoln("Update with: brew upgrade mytool")
}
}
func runNonInteractive() {
logs := generateLogs(100)
for _, log := range logs {
fmt.Println(log)
}
}
func displayWithPager(logs []string) error {
pager := terminator.NewPager()
if err := pager.Start(); err != nil {
return err
}
defer pager.Stop()
// Write header
fmt.Fprintln(pager.Out, "Application Logs")
fmt.Fprintln(pager.Out, strings.Repeat("=", 50))
fmt.Fprintln(pager.Out)
// Write logs
for i, log := range logs {
fmt.Fprintf(pager.Out, "%3d: %s\n", i+1, log)
}
return nil
}
func generateLogs(count int) []string {
logs := make([]string, count)
for i := 0; i < count; i++ {
logs[i] = fmt.Sprintf("Log entry %d", i+1)
}
return logs
}
Best Practices
- Always check IsTTY - Before using interactive features or colors
- Respect NO_COLOR - Check
IsColorDisabled() before using colors
- Handle CI environments - Use
IsCI() to skip interactive prompts
- Use pagers for long output - Improve UX for viewing large amounts of data
- Defer pager cleanup - Always use
defer pager.Stop()
- Check TTY before opening browser - Browser commands require a terminal
- Provide fallbacks - Always offer non-interactive alternatives
- Test in different environments - Test with TTY, piped output, and CI
Environment Variables
Controls which pager to use:
export PAGER="less -R" # Use less with color support
export PAGER="more" # Use more
export PAGER="cat" # Disable pager
NO_COLOR
Disables color output:
export NO_COLOR=1 # Disable colors
Indicates CI environment:
export CI=true # Mark as CI environment