summaryrefslogtreecommitdiff
path: root/internal/batch
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-07-20 22:18:57 +0300
committerPaul Buetow <paul@buetow.org>2025-07-20 22:18:57 +0300
commite580fb57a29ec3c3f3e180b20cfa6ec28687689b (patch)
treede74f04450b830268e4c1644a91acb9fd45c3802 /internal/batch
parent9e3328a6aaefe4bd1aa0ec3e8bf6e93d6033180b (diff)
Refactor main.go into focused packages
- Reduced main.go from 961 lines to 89 lines (91% reduction) - Created new packages for better separation of concerns: - cli: Command-line interface setup and configuration - processor: Core word processing logic and orchestration - batch: Batch file processing functionality - translation: Bulgarian to English translation services - models: OpenAI model listing functionality - phonetic: Phonetic information fetching - Each package has clear documentation in doc.go files - Improved testability and maintainability - All existing functionality preserved - All tests passing and build successful
Diffstat (limited to 'internal/batch')
-rw-r--r--internal/batch/doc.go4
-rw-r--r--internal/batch/processor.go94
2 files changed, 98 insertions, 0 deletions
diff --git a/internal/batch/doc.go b/internal/batch/doc.go
new file mode 100644
index 0000000..33f3b19
--- /dev/null
+++ b/internal/batch/doc.go
@@ -0,0 +1,4 @@
+// Package batch handles batch processing of Bulgarian words from files.
+// It supports reading word lists with optional translations in the format:
+// "bulgarian_word" or "bulgarian_word = english_translation"
+package batch
diff --git a/internal/batch/processor.go b/internal/batch/processor.go
new file mode 100644
index 0000000..75a38aa
--- /dev/null
+++ b/internal/batch/processor.go
@@ -0,0 +1,94 @@
+package batch
+
+import (
+ "fmt"
+ "os"
+ "strings"
+)
+
+// WordEntry represents a word with optional translation
+type WordEntry struct {
+ Bulgarian string
+ Translation string
+}
+
+// ReadBatchFile reads words from a file and returns WordEntry slice
+// Supports formats:
+// - Bulgarian word only: "ябълка"
+// - With translation: "ябълка = apple"
+func ReadBatchFile(filename string) ([]WordEntry, error) {
+ content, err := os.ReadFile(filename)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read batch file: %w", err)
+ }
+
+ var entries []WordEntry
+ lines := string(content)
+
+ for _, line := range splitLines(lines) {
+ if line = trimSpace(line); line != "" {
+ // Check if line contains '=' for bulgarian = english format
+ if strings.Contains(line, "=") {
+ parts := strings.SplitN(line, "=", 2)
+ if len(parts) == 2 {
+ bulgarian := strings.TrimSpace(parts[0])
+ english := strings.TrimSpace(parts[1])
+ if bulgarian != "" {
+ entries = append(entries, WordEntry{
+ Bulgarian: bulgarian,
+ Translation: english,
+ })
+ }
+ }
+ } else {
+ // Just a bulgarian word
+ entries = append(entries, WordEntry{
+ Bulgarian: line,
+ Translation: "",
+ })
+ }
+ }
+ }
+
+ return entries, nil
+}
+
+// splitLines splits a string by newlines
+func splitLines(s string) []string {
+ var lines []string
+ current := ""
+ for _, r := range s {
+ if r == '\n' {
+ lines = append(lines, current)
+ current = ""
+ } else if r != '\r' {
+ current += string(r)
+ }
+ }
+ if current != "" {
+ lines = append(lines, current)
+ }
+ return lines
+}
+
+// trimSpace trims whitespace from string
+func trimSpace(s string) string {
+ start := 0
+ end := len(s)
+
+ // Trim from start
+ for start < end && isSpace(rune(s[start])) {
+ start++
+ }
+
+ // Trim from end
+ for end > start && isSpace(rune(s[end-1])) {
+ end--
+ }
+
+ return s[start:end]
+}
+
+func isSpace(r rune) bool {
+ return r == ' ' || r == '\t' || r == '\n' || r == '\r'
+}