1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
// Package configui is the interactive `glint -c` walkthrough: a huh form
// that loads the current config, walks the user through every setting, and
// writes the result to the config file.
package configui
import (
"fmt"
"glint/internal/config"
"github.com/charmbracelet/huh"
)
// dailyPresets are friendly daily-note filename formats (label → Go layout), so
// users never have to write a raw Go time layout by hand.
var dailyPresets = []struct{ label, layout string }{
{"2026-06-28", "2006-01-02"},
{"2026-06-28 Sun", "2006-01-02 Mon"},
{"20260628", "20060102"},
{"2026.06.28", "2006.01.02"},
{"28-06-2026", "02-01-2006"},
}
const customLayout = "__custom__"
// Run walks the user through the settings and saves them to the config file.
func Run() error {
cfg, _ := config.Load() // defaults on error
theme := orDefault(cfg.Theme, "auto")
vaultDir := cfg.VaultDir
inboxDir := cfg.InboxDir
dailySubdir := orDefault(cfg.DailySubdir, "Daily")
glamour := cfg.GlamourStyle
spellcheck := orDefault(cfg.Spellcheck, "auto")
// Match the current layout to a preset; otherwise offer it as custom.
fmtChoice := customLayout
for _, p := range dailyPresets {
if p.layout == cfg.DailyFormat {
fmtChoice = p.layout
}
}
customFmt := cfg.DailyFormat
fmtOpts := make([]huh.Option[string], 0, len(dailyPresets)+1)
for _, p := range dailyPresets {
fmtOpts = append(fmtOpts, huh.NewOption(p.label+" ("+p.layout+")", p.layout))
}
fmtOpts = append(fmtOpts, huh.NewOption("Custom…", customLayout))
form := huh.NewForm(
huh.NewGroup(
huh.NewSelect[string]().
Title("Theme").
Description("Colors; auto follows your macOS appearance.").
Options(
huh.NewOption("auto", "auto"),
huh.NewOption("flexoki-light", "flexoki-light"),
huh.NewOption("flexoki-dark", "flexoki-dark"),
huh.NewOption("charm", "charm"),
).Value(&theme),
huh.NewInput().
Title("Vault directory").
Description("Where `glint -v` opens, from anywhere. Blank = none.").
Placeholder("/Users/you/Notes").
Value(&vaultDir),
huh.NewInput().
Title("Inbox directory").
Description("Where `glint -n -i` and save-as land. Blank = the directory you run glint in.").
Value(&inboxDir),
huh.NewInput().
Title("Daily notes subfolder").
Description("Daily notes live in <dir>/<this>/.").
Value(&dailySubdir),
huh.NewSelect[string]().
Title("Daily filename format").
Options(fmtOpts...).
Value(&fmtChoice),
huh.NewSelect[string]().
Title("Preview style").
Description("Glamour style for the read preview. Blank follows the theme.").
Options(
huh.NewOption("follow theme", ""),
huh.NewOption("dark", "dark"),
huh.NewOption("light", "light"),
huh.NewOption("dracula", "dracula"),
huh.NewOption("tokyo-night", "tokyo-night"),
).Value(&glamour),
huh.NewSelect[string]().
Title("Spellcheck").
Description("Red undercurl on misspelled prose. auto = on for notes, off for code files.").
Options(
huh.NewOption("auto", "auto"),
huh.NewOption("on", "on"),
huh.NewOption("off", "off"),
).Value(&spellcheck),
),
huh.NewGroup(
huh.NewInput().
Title("Custom daily format (Go layout)").
Description("Reference date is Mon Jan 2 2006 — e.g. 2006-01-02 or 20060102.").
Value(&customFmt),
).WithHideFunc(func() bool { return fmtChoice != customLayout }),
)
if err := form.Run(); err != nil {
return err
}
dailyFmt := fmtChoice
if fmtChoice == customLayout {
dailyFmt = customFmt
}
out := config.Config{
Theme: theme,
VaultDir: vaultDir,
InboxDir: inboxDir,
DailySubdir: dailySubdir,
DailyFormat: dailyFmt,
GlamourStyle: glamour,
Spellcheck: spellcheck,
// Export fonts aren't part of the wizard; preserve any existing values
// so a `glint -c` run doesn't silently drop them.
FontDisplay: cfg.FontDisplay,
FontBody: cfg.FontBody,
FontMono: cfg.FontMono,
}
path := config.Path()
if err := config.Save(out, path); err != nil {
return err
}
fmt.Println("Saved", path)
return nil
}
func orDefault(v, def string) string {
if v == "" {
return def
}
return v
}
|