setup base entity and change cli to print actions

This commit is contained in:
Travis Shears 2025-09-30 11:09:27 +02:00
parent d1f4527b1b
commit b24cc4d427
6 changed files with 97 additions and 26 deletions

View file

@ -3,3 +3,33 @@
Quick tool to write gemtext posts for my gemlog. Quick tool to write gemtext posts for my gemlog.
=> gemini://travisshears.com/gemlog => gemini://travisshears.com/gemlog
## Entites
Gemlog
- id, uuid
- title
- slug
- date
- gemtxt
- short? gemtxt < 250 char
## Arch
For DB planning to use couch db
## Use-cases
### Create gemlog entry
Open editor with pre-filled template with frontmatter. Set example date (now), title, slug
### Delete gemlog entry
Select from list then delete.
### Edit gemlog entry
Select from list then edit.

39
gemlog/core.go Normal file
View file

@ -0,0 +1,39 @@
package gemlog
import (
"crypto/rand"
"encoding/hex"
"fmt"
"time"
)
// GemlogEntry represents a single gemlog post entry
type GemlogEntry struct {
ID string `json:"id"`
Title string `json:"title"`
Slug string `json:"slug"`
Date time.Time `json:"date"`
Gemtxt string `json:"gemtxt"`
}
// NewUUID generates a new UUID v4 using crypto/rand
func NewUUID() (string, error) {
uuid := make([]byte, 16)
_, err := rand.Read(uuid)
if err != nil {
return "", fmt.Errorf("failed to generate UUID: %w", err)
}
// Set version (4) and variant bits according to RFC 4122
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant bits
// Format as standard UUID string: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
return fmt.Sprintf("%s-%s-%s-%s-%s",
hex.EncodeToString(uuid[0:4]),
hex.EncodeToString(uuid[4:6]),
hex.EncodeToString(uuid[6:8]),
hex.EncodeToString(uuid[8:10]),
hex.EncodeToString(uuid[10:16]),
), nil
}

0
gemlog/db.go Normal file
View file

1
gemlog/write.go Normal file
View file

@ -0,0 +1 @@
package gemlog

41
main.go
View file

@ -8,24 +8,18 @@ import (
) )
type model struct { type model struct {
cursor int cursor int
choices []string actions []string
selected map[int]struct{}
} }
func initialModel() model { func initialModel() model {
return model{ return model{
choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"}, actions: []string{"Write", "Read", "Edit", "Delete"},
// A map which indicates which choices are selected. We're using
// the map like a mathematical set. The keys refer to the indexes
// of the `choices` slice, above.
selected: make(map[int]struct{}),
} }
} }
func (m model) Init() tea.Cmd { func (m model) Init() tea.Cmd {
return tea.SetWindowTitle("Grocery List") return tea.SetWindowTitle("Gemlog CLI")
} }
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
@ -39,16 +33,16 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.cursor-- m.cursor--
} }
case "down", "j": case "down", "j":
if m.cursor < len(m.choices)-1 { if m.cursor < len(m.actions)-1 {
m.cursor++ m.cursor++
} }
case "enter", " ": // case "enter", " ":
_, ok := m.selected[m.cursor] // _, ok := m.selected[m.cursor]
if ok { // if ok {
delete(m.selected, m.cursor) // delete(m.selected, m.cursor)
} else { // } else {
m.selected[m.cursor] = struct{}{} // m.selected[m.cursor] = struct{}{}
} // }
} }
} }
@ -56,20 +50,15 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
func (m model) View() string { func (m model) View() string {
s := "What should we buy at the market?\n\n" s := "Welcome to gemlog cli!\n\nWhat would you like to do?\n\n"
for i, choice := range m.choices { for i, action := range m.actions {
cursor := " " cursor := " "
if m.cursor == i { if m.cursor == i {
cursor = ">" cursor = ">"
} }
checked := " " s += fmt.Sprintf("%s %s\n", cursor, action)
if _, ok := m.selected[i]; ok {
checked = "x"
}
s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
} }
s += "\nPress q to quit.\n" s += "\nPress q to quit.\n"

View file

@ -0,0 +1,12 @@
title: todo
date: 2025-12-31
slug: todo
tags: cat, dog
---
Example text
=> https://travisshears.com example link
* Example list item 1
* Example list item 2