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
|
// Command glint is a modeless terminal markdown editor with live styling.
package main
import (
"flag"
"fmt"
"os"
"glint/internal/app"
"glint/internal/config"
"glint/internal/configui"
"glint/internal/keyprobe"
tea "github.com/charmbracelet/bubbletea"
)
// version is the build version, overridden at release time via
// -ldflags "-X main.version=<v>" (the Homebrew formula sets it).
var version = "dev"
func main() {
// Version is the one long-only flag (-v means --vault).
if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "-version") {
fmt.Println("glint", version)
return
}
cfg, err := config.Load()
if err != nil {
fmt.Fprintln(os.Stderr, "glint: config:", err)
}
// Every command is a flag; both -x and --x (letter or word) work.
flagNew := boolFlag("n", "new")
flagToday := boolFlag("t", "today")
flagDaily := boolFlag("d", "daily")
flagVault := boolFlag("v", "vault")
flagConfig := boolFlag("c", "config")
flagInbox := boolFlag("i", "inbox")
flagKeys := flag.Bool("keys", false, "show what the terminal sends for each key")
flag.Parse()
isNew := *flagNew[0] || *flagNew[1]
isToday := *flagToday[0] || *flagToday[1]
isDaily := *flagDaily[0] || *flagDaily[1]
isVault := *flagVault[0] || *flagVault[1]
isConfig := *flagConfig[0] || *flagConfig[1]
isInbox := *flagInbox[0] || *flagInbox[1]
// Standalone commands (no editor TUI).
if isConfig {
runOrDie(configui.Run())
return
}
if *flagKeys {
runOrDie(keyprobe.Run())
return
}
name := ""
if args := flag.Args(); len(args) > 0 {
name = args[0]
}
a := app.New(cfg)
var startErr error
switch {
case isNew:
// New note in the current dir, or the inbox/vault when combined.
dir := cfg.WorkingDir()
if isInbox {
dir = cfg.InboxRoot()
}
if isVault {
dir = cfg.Vault()
}
startErr = a.StartNewIn(dir, name)
case isToday:
startErr = a.Start("", true) // today's daily note
case isVault:
startErr = a.StartPickerIn(cfg.Vault())
case isInbox:
startErr = a.StartPickerIn(cfg.InboxRoot())
case isDaily:
startErr = a.StartPickerIn(cfg.DailyDir()) // browse the daily folder
case name != "":
startErr = a.Start(name, false) // open a file
default:
startErr = a.Start("", false) // bare โ fuzzy picker over the current dir
}
if startErr != nil {
fmt.Fprintln(os.Stderr, "glint:", startErr)
os.Exit(1)
}
run(a)
}
// boolFlag registers a short and long name for the same command and returns both
// pointers; either being set means the command was given (e.g. -n / --n / -new /
// --new). Go's flag package accepts both single- and double-dash for each name.
func boolFlag(short, long string) [2]*bool {
return [2]*bool{
flag.Bool(short, false, "command: -"+short+" / --"+long),
flag.Bool(long, false, ""),
}
}
func runOrDie(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, "glint:", err)
os.Exit(1)
}
}
// run drives the Bubbletea program in the alternate screen.
func run(a *app.App) {
if _, err := tea.NewProgram(a, tea.WithAltScreen(), tea.WithMouseCellMotion()).Run(); err != nil {
fmt.Fprintln(os.Stderr, "glint:", err)
os.Exit(1)
}
}
|