all repos — bibel @ 22bb3a6ab182daf32755b4316471ff8c8f4a4fe6

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

cmd/bibel.go (view raw)

  1package main
  2
  3import (
  4	"fmt"
  5	"os"
  6	"time"
  7
  8	"github.com/alexflint/go-arg"
  9	"golang.org/x/term"
 10	"maxwelljensen/bibel/internal"
 11	"maxwelljensen/bibel/internal/tui"
 12)
 13
 14// Args defines the command line arguments
 15type Args struct {
 16	Reading        string `arg:"-r,--reading" help:"reading mode: evangelion (Gospels), new_testament, old_testament, bible (default: evangelion)"`
 17	Plain          bool   `arg:"-p,--plain" help:"output plain text without formatting or TUI"`
 18	Formatted      bool   `arg:"-f,--formatted" help:"output formatted text with ANSI colours (no TUI)"`
 19	ConfigPath     string `arg:"-c,--config" help:"path to configuration file (default: $XDG_CONFIG_HOME/bibel/config.toml)"`
 20	Numbered       bool   `arg:"-n,--numbered" help:"print each verse on a numbered line with verse number"`
 21	Paragraphs     bool   `arg:"-g,--paragraphs" help:"render pilcrows (ΒΆ) as blank lines instead of ignoring them"`
 22	Latin          bool   `arg:"-l,--latin" help:"show time until Roman Catholic Easter"`
 23	GenerateConfig bool   `arg:"--generate-config" help:"generate a default configuration file and exit"`
 24	Verbose        bool   `arg:"-v,--verbose" help:"print additional runtime information to STDOUT"`
 25}
 26
 27// Description returns a description of the program
 28func (Args) Description() string {
 29	return "Display today's Bible reading based on selected reading mode.\n" +
 30		"Reads 12 verses per day based on the current date.\n" +
 31		"Reading modes: evangelion (four Gospels), new_testament, old_testament, bible\n" +
 32		"Configuration file: $XDG_CONFIG_HOME/bibel/config.toml"
 33}
 34
 35func main() {
 36	var args Args
 37	arg.MustParse(&args)
 38
 39	// Handle config generation
 40	if args.GenerateConfig {
 41		if err := bible.GenerateDefaultConfig(); err != nil {
 42			fmt.Fprintf(os.Stderr, "Error generating config: %v\n", err)
 43			os.Exit(1)
 44		}
 45		fmt.Printf("Default configuration generated at: %s\n", bible.GetConfigPath())
 46		return
 47	}
 48
 49	// Load configuration
 50	config, err := bible.LoadConfig(args.ConfigPath, args.Verbose)
 51	if err != nil {
 52		fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
 53		os.Exit(1)
 54	}
 55
 56	// Override Easter type from command line flag if specified
 57	if args.Latin {
 58		config.EasterType = "latin"
 59	}
 60
 61	// Override reading mode from command line if specified
 62	if args.Reading != "" {
 63		config.ReadingMode = args.Reading
 64
 65		// Validate reading mode after command line override
 66		validReadingModes := map[string]bool{
 67			"evangelion":    true,
 68			"new_testament": true,
 69			"old_testament": true,
 70			"bible":         true,
 71		}
 72		if config.ReadingMode != "" && !validReadingModes[config.ReadingMode] {
 73			fmt.Fprintf(os.Stderr, "Error: invalid reading mode: %s, must be one of: evangelion, new_testament, old_testament, bible\n", config.ReadingMode)
 74			os.Exit(1)
 75		}
 76	}
 77
 78	// Load Bible data
 79	bibleData, err := bible.LoadBible(config.BiblePath, args.Verbose)
 80	if err != nil {
 81		fmt.Fprintf(os.Stderr, "Error loading Bible data: %v\n", err)
 82		os.Exit(1)
 83	}
 84
 85	// Create date progression calculator
 86	// We need to convert reading mode string to ReadingMode type
 87	// Based on verse.go, ReadingMode is a string type with constants
 88	// Create date progression calculator with reading mode from config
 89	dateProg := bible.NewDateProgressionWithReadingMode(bibleData, config.DateProgression.VersesPerDay, bible.ReadingMode(config.ReadingMode))
 90
 91	// Get today's bookmark
 92	bookmark, err := dateProg.GetPositionForDate(time.Now())
 93	if err != nil {
 94		fmt.Fprintf(os.Stderr, "Error calculating today's reading position: %v\n", err)
 95		os.Exit(1)
 96	}
 97
 98	// Determine output mode: plain, formatted, or TUI
 99	// Plain mode forces no colours, formatted respects config
100	usePlain := args.Plain
101	useFormatted := args.Formatted
102
103	// If no explicit mode but numbered/paragraphs flags are set, use formatted mode
104	if !usePlain && !useFormatted && (args.Numbered || args.Paragraphs) {
105		useFormatted = true
106	}
107
108	// If we're outputting text (plain or formatted)
109	if usePlain || useFormatted {
110		// Determine colours: plain mode = false, formatted mode = from config
111		useColours := false
112		if useFormatted {
113			useColours = config.Formatter.UseColours
114		}
115
116		// Create formatter with appropriate settings
117		formatter := bible.NewFormatterWithFullConfig(bibleData, useColours, config.Formatter.HeaderFormat, args.Numbered, args.Paragraphs)
118		header := formatter.FormatHeader(bookmark)
119		content := formatter.ExtractAndFormat(bibleData, bookmark)
120		fmt.Println(header)
121		fmt.Println(content)
122		return
123	}
124
125	// Default: TUI mode (no plain or formatted flags)
126	// Check if we're in a terminal
127	if !term.IsTerminal(int(os.Stdin.Fd())) {
128		fmt.Fprintln(os.Stderr, "Error: Standard input is not a terminal. Use --plain or --formatted for non-interactive output.")
129		os.Exit(1)
130	}
131
132	// Create and run TUI program
133	program := tui.CreateTUIProgram(bibleData, bookmark, config)
134	if _, err := program.Run(); err != nil {
135		fmt.Fprintf(os.Stderr, "Error running TUI: %v\n", err)
136		os.Exit(1)
137	}
138}
139