summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-28 21:39:49 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-28 21:39:49 +0200
commit175aa1343ff04383a5a1a8ba166505933d9be46a (patch)
tree15c5e52a08a5484fe17747ef98e649a3ea8f076f /internal
parentd5d175118138249fe7d9e85d1bc65fb0b7e3a398 (diff)
downloadlectio-175aa1343ff04383a5a1a8ba166505933d9be46a.tar.gz
lectio-175aa1343ff04383a5a1a8ba166505933d9be46a.zip
config: drop go-toml and the legacy TOML migrations
The one-shot config.toml -> config.ini and books.toml -> books.ini migrations (a transition aid from the pre-INI format) are removed, along with the github.com/pelletier/go-toml/v2 dependency and the now-dead `toml:` struct tags. The live config format has been INI for many releases; anyone still on a .toml recreates it (the format is self-documenting on first run). Leaves 3 direct deps, all in active use (bubbletea, lipgloss, go-pdf/fpdf). Tests updated to write INI.
Diffstat (limited to 'internal')
-rw-r--r--internal/config/config.go132
-rw-r--r--internal/config/config_test.go46
2 files changed, 40 insertions, 138 deletions
diff --git a/internal/config/config.go b/internal/config/config.go
index 0596194..a225a12 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -2,10 +2,8 @@
//
// Resolution order: LECTIO_CONFIG env var -> ~/.config/lectio/config.ini
// (auto-seeded from the embedded default on first run, honoring
-// XDG_CONFIG_HOME via os.UserConfigDir()) -> built-in defaults. A pre-existing
-// config.toml (lectio's former format) at the default location is converted to
-// config.ini once, on first run, and left on disk. INI that fails to parse
-// falls back to defaults with a warning on stderr.
+// XDG_CONFIG_HOME via os.UserConfigDir()) -> built-in defaults. INI that fails
+// to parse falls back to defaults with a warning on stderr.
package config
import (
@@ -16,8 +14,6 @@ import (
"strconv"
"strings"
- "github.com/pelletier/go-toml/v2"
-
"github.com/lukaszkasprzak/lectio/internal/bible"
"github.com/lukaszkasprzak/lectio/internal/calendar"
"github.com/lukaszkasprzak/lectio/internal/ini"
@@ -159,36 +155,36 @@ func NormalizeSiglaStyle(s string) string {
}
}
-// Config holds lectio's user-configurable settings. The toml tags are used only
-// by the one-shot config.toml -> config.ini migration; the live format is INI.
+// Config holds lectio's user-configurable settings. The live format is INI,
+// parsed field-by-field in readINI and written by renderConfigINI.
type Config struct {
- SchemaVersion int `toml:"schema_version"`
- Lectionary string `toml:"lectionary"`
- Versions []string `toml:"versions"`
- DefaultVersion string `toml:"default_version"`
- Width int `toml:"width"`
- All bool `toml:"all"`
- Offline bool `toml:"offline"`
- UILanguage string `toml:"ui_language"`
- ReadingLang string `toml:"reading_lang"`
- ReadingVersion string `toml:"reading_version"`
- SiglaStyle string `toml:"sigla_style"`
- WebTheme string `toml:"web_theme"`
- WebPort int `toml:"web_port"`
- WebDisplay string `toml:"web_display"`
- WebMono bool `toml:"web_mono"`
- WebVersions []string `toml:"web_versions"`
- Pager string `toml:"pager"`
- Parts map[string]map[string]bool `toml:"parts"`
+ SchemaVersion int
+ Lectionary string
+ Versions []string
+ DefaultVersion string
+ Width int
+ All bool
+ Offline bool
+ UILanguage string
+ ReadingLang string
+ ReadingVersion string
+ SiglaStyle string
+ WebTheme string
+ WebPort int
+ WebDisplay string
+ WebMono bool
+ WebVersions []string
+ Pager string
+ Parts map[string]map[string]bool
// Computed-calendar placement options (INI [calendar] section; INI-only).
- CalEpiphany string `toml:"-"`
- CalAscension string `toml:"-"`
- CalCorpusChristi string `toml:"-"`
+ CalEpiphany string
+ CalAscension string
+ CalCorpusChristi string
// Use is the ordered stack of user calendar-layer ids (INI "use"); each id
// names a <CalendarsDir>/<id>.ini file layered over the universal calendar.
- Use []string `toml:"-"`
+ Use []string
}
// PartShown reports whether a part renders: true unless explicitly set false.
@@ -403,8 +399,7 @@ func BooksPath() (string, error) {
// UserBooksINI returns the bytes of the optional user books.ini (see BooksPath),
// or nil when absent/unreadable -- callers then fall back to bible's embedded
-// default table. A former books.toml at the same location is converted to
-// books.ini once, on first read (the old file is kept).
+// default table.
func UserBooksINI() []byte {
p, err := BooksPath()
if err != nil {
@@ -413,59 +408,7 @@ func UserBooksINI() []byte {
if b, err := os.ReadFile(p); err == nil {
return b
}
- tomlPath := filepath.Join(filepath.Dir(p), "books.toml")
- data, err := os.ReadFile(tomlPath)
- if err != nil {
- return nil
- }
- out := booksTOMLtoINI(data)
- if out == nil {
- return nil
- }
- _ = os.WriteFile(p, out, 0o644)
- fmt.Fprintf(os.Stderr, "lectio: migrated %s -> books.ini (old file kept)\n", tomlPath)
- return out
-}
-
-// booksTOMLtoINI converts a former books.toml (dialect -> book -> [forms]) into
-// books.ini. Returns nil if the TOML is unparseable.
-func booksTOMLtoINI(data []byte) []byte {
- var raw map[string]map[string][]string
- if err := toml.Unmarshal(data, &raw); err != nil {
- return nil
- }
- var b strings.Builder
- b.WriteString("# lectio book names & abbreviations, per dialect (migrated from books.toml).\n")
- emit := func(d string) {
- books := raw[d]
- if books == nil {
- return
- }
- fmt.Fprintf(&b, "\n[%s]\n", d)
- keys := make([]string, 0, len(books))
- for k := range books {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, k := range keys {
- fmt.Fprintf(&b, "%s = %s\n", k, strings.Join(books[k], ", "))
- }
- }
- seen := map[string]bool{"en": true, "pl": true, "la": true}
- emit("en")
- emit("pl")
- emit("la")
- others := make([]string, 0)
- for d := range raw {
- if !seen[d] {
- others = append(others, d)
- }
- }
- sort.Strings(others)
- for _, d := range others {
- emit(d)
- }
- return []byte(b.String())
+ return nil
}
// seedIfMissing writes the embedded default config to path if nothing is
@@ -482,24 +425,6 @@ func seedIfMissing(path string) error {
return os.WriteFile(path, renderConfigINI(Default()), 0o644)
}
-// migrateFromTOML converts a former config.toml sitting next to iniPath into
-// config.ini, once. The old file is left in place (so the change is
-// reversible). A missing or unreadable config.toml is not an error.
-func migrateFromTOML(iniPath string) {
- tomlPath := filepath.Join(filepath.Dir(iniPath), "config.toml")
- data, err := os.ReadFile(tomlPath)
- if err != nil {
- return
- }
- cfg := Default()
- if err := toml.Unmarshal(data, &cfg); err != nil {
- return
- }
- normalize(&cfg)
- _ = Save(cfg) // writes config.ini
- fmt.Fprintf(os.Stderr, "lectio: migrated %s -> config.ini (old file kept)\n", tomlPath)
-}
-
// Load reads lectio's configuration, following the package's resolution order
// (see the package doc comment). It always returns a usable Config: on a
// missing config dir or an INI parse error it falls back to Default() (warning
@@ -516,7 +441,6 @@ func Load() (Config, error) {
if isDefault {
if _, statErr := os.Stat(path); os.IsNotExist(statErr) {
- migrateFromTOML(path) // convert a former config.toml if present
if err := seedIfMissing(path); err != nil {
return def, err
}
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index dd75808..4d172c0 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -68,8 +68,8 @@ func TestLoadOverride(t *testing.T) {
dir := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", dir)
os.MkdirAll(filepath.Join(dir, "lectio"), 0o755)
- os.WriteFile(filepath.Join(dir, "lectio", "config.toml"),
- []byte("offline = true\ndefault_version = \"wuj\"\n"), 0o644)
+ os.WriteFile(filepath.Join(dir, "lectio", "config.ini"),
+ []byte("offline = true\ndefault_version = wuj\n"), 0o644)
cfg, _ := Load()
if !cfg.Offline || cfg.DefaultVersion != "wuj" {
t.Errorf("override not applied: %+v", cfg)
@@ -121,8 +121,8 @@ func TestWebDisplayLoadsSetting(t *testing.T) {
dir := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", dir)
os.MkdirAll(filepath.Join(dir, "lectio"), 0o755)
- os.WriteFile(filepath.Join(dir, "lectio", "config.toml"),
- []byte("web_display = \"vertical\"\n"), 0o644)
+ os.WriteFile(filepath.Join(dir, "lectio", "config.ini"),
+ []byte("web_display = vertical\n"), 0o644)
cfg, err := Load()
if err != nil {
t.Fatal(err)
@@ -136,8 +136,8 @@ func TestWebDisplayNormalizesUnknown(t *testing.T) {
dir := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", dir)
os.MkdirAll(filepath.Join(dir, "lectio"), 0o755)
- os.WriteFile(filepath.Join(dir, "lectio", "config.toml"),
- []byte("web_display = \"bogus\"\n"), 0o644)
+ os.WriteFile(filepath.Join(dir, "lectio", "config.ini"),
+ []byte("web_display = bogus\n"), 0o644)
cfg, err := Load()
if err != nil {
t.Fatal(err)
@@ -158,8 +158,8 @@ func TestUILanguageLoadsPL(t *testing.T) {
dir := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", dir)
os.MkdirAll(filepath.Join(dir, "lectio"), 0o755)
- os.WriteFile(filepath.Join(dir, "lectio", "config.toml"),
- []byte("ui_language = \"pl\"\n"), 0o644)
+ os.WriteFile(filepath.Join(dir, "lectio", "config.ini"),
+ []byte("ui_language = pl\n"), 0o644)
cfg, err := Load()
if err != nil {
t.Fatal(err)
@@ -176,8 +176,8 @@ func TestUILanguagePreservesAnyCode(t *testing.T) {
dir := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", dir)
os.MkdirAll(filepath.Join(dir, "lectio"), 0o755)
- os.WriteFile(filepath.Join(dir, "lectio", "config.toml"),
- []byte("ui_language = \"FR\"\n"), 0o644)
+ os.WriteFile(filepath.Join(dir, "lectio", "config.ini"),
+ []byte("ui_language = FR\n"), 0o644)
cfg, err := Load()
if err != nil {
t.Fatal(err)
@@ -210,8 +210,8 @@ func TestPagerLoadsSetting(t *testing.T) {
dir := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", dir)
os.MkdirAll(filepath.Join(dir, "lectio"), 0o755)
- os.WriteFile(filepath.Join(dir, "lectio", "config.toml"),
- []byte("pager = \"less -R\"\n"), 0o644)
+ os.WriteFile(filepath.Join(dir, "lectio", "config.ini"),
+ []byte("pager = less -R\n"), 0o644)
cfg, err := Load()
if err != nil {
t.Fatal(err)
@@ -303,28 +303,6 @@ func TestUseLayers(t *testing.T) {
}
}
-func TestMigrateTOMLToINI(t *testing.T) {
- dir := t.TempDir()
- t.Setenv("XDG_CONFIG_HOME", dir)
- os.MkdirAll(filepath.Join(dir, "lectio"), 0o755)
- // only the old TOML exists -> Load converts once and writes config.ini.
- os.WriteFile(filepath.Join(dir, "lectio", "config.toml"),
- []byte("ui_language = \"pl\"\ndefault_version = \"wuj\"\n"), 0o644)
- cfg, err := Load()
- if err != nil {
- t.Fatal(err)
- }
- if cfg.UILanguage != "pl" || cfg.DefaultVersion != "wuj" {
- t.Errorf("migrated values wrong: %+v", cfg)
- }
- if _, err := os.Stat(filepath.Join(dir, "lectio", "config.ini")); err != nil {
- t.Error("config.ini not written on migration")
- }
- if _, err := os.Stat(filepath.Join(dir, "lectio", "config.toml")); err != nil {
- t.Error("old config.toml should be kept (reversible)")
- }
-}
-
func TestPartShown(t *testing.T) {
var empty Config
if !empty.PartShown("new", "psalm") {