all repos — bibel @ 9410cd8d1fb198ef5a049c595cb51e4f5587e5e7

Unnamed repository; edit this file 'description' to name the repository.

internal/formatter.go (view raw)

  1package bible
  2
  3import (
  4	"fmt"
  5	"strings"
  6)
  7
  8// Formatter handles formatting Bible text for display
  9type Formatter struct {
 10	bible        *Bible
 11	useColours   bool
 12	headerFormat string
 13}
 14
 15// NewFormatter creates a new formatter with default settings
 16func NewFormatter(bible *Bible) *Formatter {
 17	return &Formatter{
 18		bible:        bible,
 19		useColours:   true,
 20		headerFormat: "{book} {chapter}\nv. {first_verse}-{second_verse}",
 21	}
 22}
 23
 24// NewFormatterWithConfig creates a new formatter with configuration
 25func NewFormatterWithConfig(bible *Bible, useColours bool, headerFormat string) *Formatter {
 26	return &Formatter{
 27		bible:        bible,
 28		useColours:   useColours,
 29		headerFormat: headerFormat,
 30	}
 31}
 32
 33// FormatHeader formats the header for a bookmark using the configured template
 34func (f *Formatter) FormatHeader(bookmark *Bookmark) string {
 35	template := f.headerFormat
 36	if template == "" {
 37		// Fall back to default template
 38		template = "{book} {chapter}\nv. {first_verse}-{second_verse}"
 39	}
 40
 41	// Get book name from Bible data
 42	bookName := f.getBookName(bookmark.Book)
 43
 44	// Replace template variables
 45	result := template
 46	result = strings.ReplaceAll(result, "{book}", bookName)
 47	result = strings.ReplaceAll(result, "{chapter}", fmt.Sprintf("%d", bookmark.Chapter))
 48	result = strings.ReplaceAll(result, "{first_verse}", fmt.Sprintf("%d", bookmark.FirstVerse))
 49	result = strings.ReplaceAll(result, "{second_verse}", fmt.Sprintf("%d", bookmark.SecondVerse))
 50
 51	if !f.useColours {
 52		return result
 53	}
 54
 55	// Add ANSI colours - simple implementation
 56	// For more advanced templating, we'd need a proper template engine
 57	const (
 58		reset  = "\033[0m"
 59		green  = "\033[32m"
 60		yellow = "\033[33m"
 61	)
 62
 63	// Simple colouring - book and chapter in green, verse range in yellow
 64	lines := strings.Split(result, "\n")
 65	if len(lines) >= 1 {
 66		lines[0] = green + lines[0] + reset
 67	}
 68	if len(lines) >= 2 {
 69		lines[1] = yellow + lines[1] + reset
 70	}
 71	result = strings.Join(lines, "\n")
 72
 73	return result
 74}
 75
 76// getBookName retrieves the book name from Bible data
 77func (f *Formatter) getBookName(book BookIndex) string {
 78	// Try to find any verse from this book to get the book name
 79	// Start from chapter 1, verse 1 and work forward
 80	for chapter := 1; chapter <= 150; chapter++ {
 81		for verse := 1; verse <= 200; verse++ {
 82			if v, ok := f.bible.GetVerse(int(book), chapter, verse); ok {
 83				return v.BookName
 84			}
 85		}
 86	}
 87	// If we can't find the book in the data, return a generic name
 88	return fmt.Sprintf("Book %d", book)
 89} // FormatHeaderWithTemplate is deprecated - use FormatHeader instead
 90func (f *Formatter) FormatHeaderWithTemplate(bookmark *Bookmark) string {
 91	return f.FormatHeader(bookmark)
 92}
 93
 94// FormatSnippet formats the verse range text
 95func (f *Formatter) FormatSnippet(verses []*Verse) string {
 96	if len(verses) == 0 {
 97		return "Error: No text matched"
 98	}
 99
100	var sb strings.Builder
101	for i, verse := range verses {
102		if i > 0 {
103			sb.WriteString(" ")
104		}
105		// Remove any leading pilcrow (¶) and trim
106		text := strings.TrimSpace(verse.Text)
107		if strings.HasPrefix(text, "¶ ") {
108			text = text[2:]
109		} else if strings.HasPrefix(text, "¶") {
110			text = text[1:]
111		}
112		sb.WriteString(text)
113	}
114
115	return sb.String()
116}
117
118// ExtractAndFormat extracts verses for a bookmark and formats them
119func (f *Formatter) ExtractAndFormat(bible *Bible, bookmark *Bookmark) string {
120	verses := bible.GetVerseRange(int(bookmark.Book), bookmark.Chapter,
121		bookmark.FirstVerse, bookmark.SecondVerse)
122	return f.FormatSnippet(verses)
123}
124
125// ExtractAndFormatWithHeader extracts verses and formats with header
126func (f *Formatter) ExtractAndFormatWithHeader(bible *Bible, bookmark *Bookmark) string {
127	header := f.FormatHeader(bookmark)
128	content := f.ExtractAndFormat(bible, bookmark)
129	return header + "\n" + content
130}
131