1

I was experimenting with creack/pty while learning about pseudo terminals.

I spawned grep and hooked it up with a pseudo terminal device as follows:

package main

import (
    "fmt"
    "log"
    "os/exec"

    "github.com/creack/pty"
)

func main() {
    // Command to run
    cmd := exec.Command("grep", "--color=always", "-E", "pattern") // replace "pattern" with your regex

    // Start the command with a pseudo-terminal
    ptmx, err := pty.Start(cmd)
    if err != nil {
        log.Fatal(err)
    }
    defer func() { _ = ptmx.Close() }() // close pty when done

    // Input text to grep
    input := "this is a test line\npattern matched here\nanother line\n\004"

    // Write input to the pty
    _, err = ptmx.Write([]byte(input))
    if err != nil {
        log.Fatal(err)
    }

    // Read the output from grep
    buf := make([]byte, 1024)
    n, err := ptmx.Read(buf)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s", string(buf[:n]))
}

However, I could not find the ASCII sequences for highlighting in the output. I even used debugger to see if anything was wrong with my terminal. But no, even the buf buffer does not contain the ASCII sequences.

Isn't grep supposed to output highlighting ASCII sequences when --color=always is used?

What might I be missing here?

1
  • 1
    There might be a race condition (e.g. grep still detecting terminal capabilities). Waiting a bit right before reading, e.g. using time.Sleep(10 * time.Millisecond) or err = cmd.Wait() both seem to work. Commented Nov 13 at 11:14

1 Answer 1

1

The problem was that you didn't read the full output of the command. Instead you're just reading the initial batch of them. You may read the entire output with loop.

package main

import (
    "fmt"
    "log"
    "os/exec"

    "github.com/creack/pty"
)

func main() {
    // Command to run
    cmd := exec.Command("grep", "--color=always", "-E", "pattern") // replace "pattern" with your regex

    // Start the command with a pseudo-terminal
    ptmx, err := pty.Start(cmd)
    if err != nil {
        log.Fatal(err)
    }
    defer func() { _ = ptmx.Close() }() // close pty when done

    // Input text to grep
    input := "this is a test line\npattern matched here\nanother line\nhello world\n\004"

    // Write input to the pty
    _, err = ptmx.Write([]byte(input))
    if err != nil {
        log.Fatal(err)
    }

    // Read the output from grep
    buf := make([]byte, 1024)
    for {
        n, err := ptmx.Read(buf)
        if n > 0 {
            fmt.Printf("%s", string(buf[:n]))
        }
        if err != nil {
            break
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.