summaryrefslogtreecommitdiff
path: root/internal/batch
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-02 21:47:12 +0300
committerPaul Buetow <paul@buetow.org>2026-04-02 21:47:12 +0300
commit993b2efe63e221cee550756770894c9c58474d25 (patch)
tree126b0dad9e1225c575f2521f29c6ad68556f4056 /internal/batch
parentdac35c77721c97f093a44d98164b38534452de9f (diff)
task 00g/00k/00h/008: gofmt, remove ProviderWithFallback, stdlib helpers, shared prompt
- task 00g: fix gofmt violations (trailing whitespace, missing newlines, indentation) in 8 files; all pass gofmt -l now - task 00k: remove unused ProviderWithFallback and its tests (YAGNI — no production caller existed; voice-level fallback via RunWithVoiceFallbacks already covers the real use case) - task 00h: replace private splitLines/trimSpace/isSpace helpers in internal/batch/processor.go with strings.Split+ReplaceAll and strings.TrimSpace from the stdlib; remove the now-redundant tests - task 008: extract buildEducationalPrompt into internal/image/prompt.go so the prompt-assembly policy (scene truncation cascade, char limit) lives in one place; both OpenAIClient and NanoBananaClient delegate to it Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/batch')
-rw-r--r--internal/batch/processor.go49
-rw-r--r--internal/batch/processor_test.go134
2 files changed, 5 insertions, 178 deletions
diff --git a/internal/batch/processor.go b/internal/batch/processor.go
index 314d67f..2b002a9 100644
--- a/internal/batch/processor.go
+++ b/internal/batch/processor.go
@@ -31,10 +31,11 @@ func ReadBatchFile(filename string) ([]WordEntry, error) {
}
var entries []WordEntry
- lines := string(content)
-
- for _, line := range splitLines(lines) {
- if line = trimSpace(line); line != "" {
+ // Normalize \r\n to \n before splitting so both Windows and Unix line
+ // endings are handled uniformly by strings.Split.
+ normalized := strings.ReplaceAll(string(content), "\r\n", "\n")
+ for _, line := range strings.Split(normalized, "\n") {
+ if line = strings.TrimSpace(line); line != "" {
entry := parseBatchLine(line)
if entry != nil {
entries = append(entries, *entry)
@@ -103,43 +104,3 @@ func parseBatchLine(line string) *WordEntry {
}
}
-// splitLines splits a string by newlines, handling both \n and \r\n line endings.
-// Uses strings.Builder to avoid per-character heap allocations from += concatenation.
-func splitLines(s string) []string {
- var lines []string
- var current strings.Builder
- for _, r := range s {
- if r == '\n' {
- lines = append(lines, current.String())
- current.Reset()
- } else if r != '\r' {
- current.WriteRune(r)
- }
- }
- if current.Len() > 0 {
- lines = append(lines, current.String())
- }
- 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'
-}
diff --git a/internal/batch/processor_test.go b/internal/batch/processor_test.go
index fc4f7b0..8bc8079 100644
--- a/internal/batch/processor_test.go
+++ b/internal/batch/processor_test.go
@@ -163,137 +163,3 @@ func TestReadBatchFile_FileNotFound(t *testing.T) {
}
}
-func TestSplitLines(t *testing.T) {
- tests := []struct {
- name string
- input string
- want []string
- }{
- {
- name: "unix line endings",
- input: "line1\nline2\nline3",
- want: []string{"line1", "line2", "line3"},
- },
- {
- name: "windows line endings",
- input: "line1\r\nline2\r\nline3",
- want: []string{"line1", "line2", "line3"},
- },
- {
- name: "mixed line endings",
- input: "line1\nline2\r\nline3",
- want: []string{"line1", "line2", "line3"},
- },
- {
- name: "empty string",
- input: "",
- want: nil,
- },
- {
- name: "single line no ending",
- input: "single line",
- want: []string{"single line"},
- },
- {
- name: "trailing newline",
- input: "line1\nline2\n",
- want: []string{"line1", "line2"},
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got := splitLines(tt.input)
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("splitLines() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestTrimSpace(t *testing.T) {
- tests := []struct {
- name string
- input string
- want string
- }{
- {
- name: "no whitespace",
- input: "hello",
- want: "hello",
- },
- {
- name: "leading spaces",
- input: " hello",
- want: "hello",
- },
- {
- name: "trailing spaces",
- input: "hello ",
- want: "hello",
- },
- {
- name: "both sides",
- input: " hello ",
- want: "hello",
- },
- {
- name: "tabs and spaces",
- input: "\t hello \t",
- want: "hello",
- },
- {
- name: "newlines",
- input: "\nhello\n",
- want: "hello",
- },
- {
- name: "all whitespace types",
- input: " \t\n\rhello \t\n\r",
- want: "hello",
- },
- {
- name: "empty string",
- input: "",
- want: "",
- },
- {
- name: "only whitespace",
- input: " \t\n\r ",
- want: "",
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got := trimSpace(tt.input)
- if got != tt.want {
- t.Errorf("trimSpace() = %q, want %q", got, tt.want)
- }
- })
- }
-}
-
-func TestIsSpace(t *testing.T) {
- tests := []struct {
- r rune
- want bool
- }{
- {' ', true},
- {'\t', true},
- {'\n', true},
- {'\r', true},
- {'a', false},
- {'1', false},
- {'!', false},
- {0, false},
- }
-
- for _, tt := range tests {
- t.Run(string(tt.r), func(t *testing.T) {
- if got := isSpace(tt.r); got != tt.want {
- t.Errorf("isSpace(%q) = %v, want %v", tt.r, got, tt.want)
- }
- })
- }
-}