|
|
@ -7,6 +7,8 @@ import (
|
|
|
|
"strings"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
"flag"
|
|
|
|
"flag"
|
|
|
|
|
|
|
|
"bufio"
|
|
|
|
|
|
|
|
"os"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/chzyer/readline"
|
|
|
|
"github.com/chzyer/readline"
|
|
|
|
"github.com/gopxl/beep"
|
|
|
|
"github.com/gopxl/beep"
|
|
|
@ -39,55 +41,72 @@ func main() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Configure readline settings
|
|
|
|
var input string
|
|
|
|
rl, err := readline.NewEx(&readline.Config{
|
|
|
|
|
|
|
|
Prompt: "> ", // Use a simple prompt for each line input
|
|
|
|
|
|
|
|
InterruptPrompt: "^C",
|
|
|
|
|
|
|
|
EOFPrompt: "exit",
|
|
|
|
|
|
|
|
FuncFilterInputRune: uppercaseFilter, // Filter to show uppercase
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
fmt.Printf("Error initializing readline: %s\n", err)
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
defer rl.Close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Inform the user about how to enter input
|
|
|
|
// Check if input is being redirected from a file
|
|
|
|
fmt.Println("Enter text to be read (A-Z and 0-9 only). Press Enter on a blank line to process:")
|
|
|
|
if isInputFromPipe() {
|
|
|
|
|
|
|
|
// Read from stdin (file input)
|
|
|
|
var inputBuilder strings.Builder
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
|
|
for {
|
|
|
|
var inputBuilder strings.Builder
|
|
|
|
line, err := rl.Readline()
|
|
|
|
for scanner.Scan() {
|
|
|
|
if err != nil {
|
|
|
|
line := scanner.Text()
|
|
|
|
if err.Error() == "EOF" {
|
|
|
|
inputBuilder.WriteString(line + "\n")
|
|
|
|
fmt.Println("Exiting.")
|
|
|
|
}
|
|
|
|
return
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("Error reading input: %s\n", err)
|
|
|
|
fmt.Printf("Error reading input: %s\n", err)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
input = inputBuilder.String()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Use readline for interactive input
|
|
|
|
|
|
|
|
rl, err := readline.NewEx(&readline.Config{
|
|
|
|
|
|
|
|
Prompt: "> ", // Use a simple prompt for each line input
|
|
|
|
|
|
|
|
InterruptPrompt: "^C",
|
|
|
|
|
|
|
|
EOFPrompt: "exit",
|
|
|
|
|
|
|
|
FuncFilterInputRune: uppercaseFilter, // Filter to show uppercase
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
fmt.Printf("Error initializing readline: %s\n", err)
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
defer rl.Close()
|
|
|
|
|
|
|
|
|
|
|
|
// Check if the user entered a blank line to finish input
|
|
|
|
// Inform the user about how to enter input
|
|
|
|
if strings.TrimSpace(line) == "" {
|
|
|
|
fmt.Println("Enter text to be read (A-Z and 0-9 only). Press Enter on a blank line to process:")
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
var inputBuilder strings.Builder
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
|
|
|
line, err := rl.Readline()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
if err.Error() == "EOF" {
|
|
|
|
|
|
|
|
fmt.Println("Exiting.")
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("Error reading input: %s\n", err)
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if the user entered a blank line to finish input
|
|
|
|
|
|
|
|
if strings.TrimSpace(line) == "" {
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Append the line to the input builder
|
|
|
|
|
|
|
|
inputBuilder.WriteString(line + "\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Append the line to the input builder
|
|
|
|
input = inputBuilder.String()
|
|
|
|
inputBuilder.WriteString(line + "\n")
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Get the complete input as a string
|
|
|
|
// Process the input
|
|
|
|
input := inputBuilder.String()
|
|
|
|
|
|
|
|
input = strings.ToLower(strings.TrimSpace(input))
|
|
|
|
input = strings.ToLower(strings.TrimSpace(input))
|
|
|
|
|
|
|
|
|
|
|
|
// Split the input into sections and process each section
|
|
|
|
|
|
|
|
sections := strings.FieldsFunc(input, func(r rune) bool {
|
|
|
|
sections := strings.FieldsFunc(input, func(r rune) bool {
|
|
|
|
return r == ' ' || r == '-' || r == '_'
|
|
|
|
return r == ' ' || r == '-' || r == '_'
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Println("Playback starting...")
|
|
|
|
fmt.Println("Beginning playback...")
|
|
|
|
|
|
|
|
|
|
|
|
for _, section := range sections {
|
|
|
|
for _, section := range sections {
|
|
|
|
// Determine the number of times to read each section
|
|
|
|
|
|
|
|
numRepeats := 1
|
|
|
|
numRepeats := 1
|
|
|
|
if *repeat {
|
|
|
|
if *repeat {
|
|
|
|
numRepeats = 2
|
|
|
|
numRepeats = 2
|
|
|
@ -115,6 +134,12 @@ func main() {
|
|
|
|
fmt.Println("Playback finished. Exiting.")
|
|
|
|
fmt.Println("Playback finished. Exiting.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Function to check if input is from a pipe or file
|
|
|
|
|
|
|
|
func isInputFromPipe() bool {
|
|
|
|
|
|
|
|
fileInfo, _ := os.Stdin.Stat()
|
|
|
|
|
|
|
|
return (fileInfo.Mode() & os.ModeCharDevice) == 0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Function to play sound
|
|
|
|
// Function to play sound
|
|
|
|
func playSound(soundData []byte) {
|
|
|
|
func playSound(soundData []byte) {
|
|
|
|
streamer, format, err := wav.Decode(bytes.NewReader(soundData))
|
|
|
|
streamer, format, err := wav.Decode(bytes.NewReader(soundData))
|
|
|
|