|
|
@ -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"
|
|
|
@ -24,7 +26,7 @@ const (
|
|
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
func main() {
|
|
|
|
// Define and parse the -r flag
|
|
|
|
// Define and parse the -r flag
|
|
|
|
repeat := flag.Bool("r", false, "Repeat each section separated by space, '-', or '_'")
|
|
|
|
repeat := flag.Bool("r", false, "Repeat each section separated by space, '-', '_', or a new line")
|
|
|
|
flag.Parse()
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
|
|
|
|
// Create a map to store sound data for each character
|
|
|
|
// Create a map to store sound data for each character
|
|
|
@ -39,55 +41,80 @@ func main() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Configure readline settings
|
|
|
|
var input string
|
|
|
|
rl, err := readline.NewEx(&readline.Config{
|
|
|
|
|
|
|
|
Prompt: "> ", // Use a simple prompt for each line input
|
|
|
|
if *repeat {
|
|
|
|
InterruptPrompt: "^C",
|
|
|
|
fmt.Println("Repeat mode is ON")
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
|
|
// Check if the user entered a blank line to finish input
|
|
|
|
// Display the input, filtered to uppercase, before playback
|
|
|
|
if strings.TrimSpace(line) == "" {
|
|
|
|
fmt.Println("Input:\n")
|
|
|
|
break
|
|
|
|
fmt.Println(strings.ToUpper(input))
|
|
|
|
|
|
|
|
} 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()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Inform the user about how to enter input
|
|
|
|
|
|
|
|
fmt.Println("Enter text to be read (A-Z and 0-9 only). Press Enter on a blank line to process:")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 == '_' || r == '\n' || r == '\r'
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Println("Playback starting...")
|
|
|
|
fmt.Print("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 +142,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))
|
|
|
|