setup base entity and change cli to print actions
This commit is contained in:
parent
d1f4527b1b
commit
b24cc4d427
6 changed files with 97 additions and 26 deletions
30
README.md
30
README.md
|
|
@ -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
39
gemlog/core.go
Normal 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
0
gemlog/db.go
Normal file
1
gemlog/write.go
Normal file
1
gemlog/write.go
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
package gemlog
|
||||||
39
main.go
39
main.go
|
|
@ -9,23 +9,17 @@ 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"
|
||||||
|
|
|
||||||
12
templates/default_post.gmi
Normal file
12
templates/default_post.gmi
Normal 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue