User config, custom journal dir
This commit is contained in:
@@ -0,0 +1,90 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
JournalDir string `toml:"journal_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Default() (Config, error) {
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, fmt.Errorf("cannot determine home dir: %w", err)
|
||||||
|
}
|
||||||
|
return Config{
|
||||||
|
JournalDir: filepath.Join(home, "journal"),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Path() (string, error) {
|
||||||
|
cd, err := os.UserConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("could not determine user config dir: %w", err)
|
||||||
|
}
|
||||||
|
configPath := filepath.Join(cd, "journal.toml")
|
||||||
|
return configPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadOrCreate() (Config, bool, error) {
|
||||||
|
|
||||||
|
configPath, err := Path()
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, false, fmt.Errorf("could not determine user config dir: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Open(configPath)
|
||||||
|
|
||||||
|
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
|
fmt.Printf("\n\nerr: %v %T\n\n", err, err)
|
||||||
|
return Config{}, false, fmt.Errorf("could not open user config '%s': %w", configPath, err)
|
||||||
|
} else if err != nil { // not exist
|
||||||
|
f, err = os.Create(configPath)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, false, fmt.Errorf("could not create user config '%s': %w", configPath, err)
|
||||||
|
}
|
||||||
|
def, err := Default()
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, false, fmt.Errorf("could not generate default config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = toml.NewEncoder(f).Encode(def)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, false, fmt.Errorf("could not encode new config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, false, fmt.Errorf("could not close file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return def, true, createJournalDirIfNecessary(def)
|
||||||
|
} else {
|
||||||
|
config := Config{}
|
||||||
|
err = toml.NewDecoder(f).Decode(&config)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, false, fmt.Errorf("could not decode config in '%s': %w", configPath, err)
|
||||||
|
}
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, false, fmt.Errorf("could not close file: %w", err)
|
||||||
|
}
|
||||||
|
return config, false, createJournalDirIfNecessary(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createJournalDirIfNecessary(c Config) error {
|
||||||
|
err := os.Mkdir(c.JournalDir, 0777)
|
||||||
|
if err != nil && errors.Is(err, os.ErrExist) {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ require (
|
|||||||
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.24 // indirect
|
github.com/mattn/go-runewidth v0.0.24 // indirect
|
||||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.4.3
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
golang.org/x/sync v0.21.0 // indirect
|
golang.org/x/sync v0.21.0 // indirect
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/a
|
|||||||
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
|
|||||||
@@ -15,10 +15,23 @@ import (
|
|||||||
"charm.land/bubbles/v2/textarea"
|
"charm.land/bubbles/v2/textarea"
|
||||||
tea "charm.land/bubbletea/v2"
|
tea "charm.land/bubbletea/v2"
|
||||||
"charm.land/lipgloss/v2"
|
"charm.land/lipgloss/v2"
|
||||||
|
"code.ppl.town/justin/journal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
p := tea.NewProgram(initialModel())
|
|
||||||
|
cfg, created, err := config.LoadOrCreate()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("could not get config: %s", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if created {
|
||||||
|
cp, _ := config.Path()
|
||||||
|
fmt.Printf("configuration created at '%s' - please check and re-run\n", cp)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := tea.NewProgram(initialModel(cfg))
|
||||||
|
|
||||||
if _, err := p.Run(); err != nil {
|
if _, err := p.Run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -43,13 +56,8 @@ type model struct {
|
|||||||
transientMsgs []transientMsg
|
transientMsgs []transientMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWriter() (WriteSeekCloser, error) {
|
func getWriter(cfg config.Config) (WriteSeekCloser, error) {
|
||||||
hd, err := os.UserHomeDir()
|
fp := cfg.JournalDir
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fp := filepath.Join(hd, "journal")
|
|
||||||
fpS, err := os.Stat(fp)
|
fpS, err := os.Stat(fp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -67,7 +75,7 @@ func getWriter() (WriteSeekCloser, error) {
|
|||||||
return file, nil
|
return file, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initialModel() model {
|
func initialModel(cfg config.Config) model {
|
||||||
ti := textarea.New()
|
ti := textarea.New()
|
||||||
ti.Placeholder = "What's happening Peter ..."
|
ti.Placeholder = "What's happening Peter ..."
|
||||||
ti.SetVirtualCursor(false)
|
ti.SetVirtualCursor(false)
|
||||||
@@ -77,7 +85,7 @@ func initialModel() model {
|
|||||||
ti.SetHeight(20)
|
ti.SetHeight(20)
|
||||||
ti.SetWidth(80)
|
ti.SetWidth(80)
|
||||||
|
|
||||||
fh, err := getWriter()
|
fh, err := getWriter(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user