diff --git a/compositor/compositor.go b/compositor/compositor.go index 20aa1e1..041e5b3 100644 --- a/compositor/compositor.go +++ b/compositor/compositor.go @@ -3,6 +3,8 @@ I asked for very little ( a dialog box ) from life ( bubbletea ), and even this I guess asking for an functional overlay was too much in 2025 so here is my own compositor layer. Idea is simple really I just draw the old ui and then on top draw the new ui, only overwriting what's needed The main problem is with handling of characters and styles which is "decent" enough here. + +NOTE: I had this module written at some point but I don't use it now - ruinivist, 1Jan26 */ diff --git a/fstree/fs.go b/fs.go similarity index 95% rename from fstree/fs.go rename to fs.go index 488d827..3e6ed00 100644 --- a/fstree/fs.go +++ b/fs.go @@ -1,12 +1,9 @@ /* This file has the raw file io operations that are used by FsTree -or elsewhere in the app. Nowhere else should there be a direct -fileopen - - ruinivist, 30Dec25 */ -package fstree +package main import ( "errors" diff --git a/fstree/fstree.go b/fstree.go similarity index 99% rename from fstree/fstree.go rename to fstree.go index a4c5a25..94431a0 100644 --- a/fstree/fstree.go +++ b/fstree.go @@ -5,7 +5,7 @@ It is initialised at startup and used for state changes in UI and later persiste - ruinivist, 30Dec25 */ -package fstree +package main import ( "errors" diff --git a/main.go b/main.go index b2d6639..04e0ffc 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - fs "mend/fstree" "os" "github.com/charmbracelet/bubbles/spinner" @@ -38,7 +37,7 @@ type model struct { width int terminalWidth int terminalHeight int - tree *fs.FsTree + tree *FsTree rootPath string // path to load the tree from // spinner needs to be state as I need to update the spinner on // each tick in update func @@ -69,7 +68,7 @@ func createModel(rootPath string) model { // these need to be on the "model" ( duck typing "implements" interface ) type treeLoadedMsg struct { - tree *fs.FsTree + tree *FsTree } func loadTreeCmd(path string) tea.Cmd { @@ -85,7 +84,7 @@ func loadTreeCmd(path string) tea.Cmd { } else { targetPath = path } - return treeLoadedMsg{tree: fs.NewFsTree(targetPath)} + return treeLoadedMsg{tree: NewFsTree(targetPath)} } } @@ -141,7 +140,12 @@ func (m model) View() string { return fmt.Sprintf("%s Loading files...", m.spinner.View()) } - return m.tree.View() + tree := m.tree.View() + full := lipgloss.JoinHorizontal( + lipgloss.Top, + tree, + ) + return full } // =================== bubbletea ui fns =================== diff --git a/notes.go b/notes.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/notes.go @@ -0,0 +1 @@ +package main diff --git a/notes/notes.go b/notes/notes.go new file mode 100644 index 0000000..97c0a4e --- /dev/null +++ b/notes/notes.go @@ -0,0 +1,116 @@ +/* +this pakckage basically handles notes which are the individual files for spaced +repetition in mend +- ruinivist, 3Jan26 +*/ + +package notes + +import ( + "os" + "strings" + + tea "github.com/charmbracelet/bubbletea" +) + +type Model struct { + path string + title string // the first line is always # title + content string // strip the first line from file rest is content + hints []string //a hint is anything that matches (hint: ) in content + err error + loading bool +} + +// ================== messages =================== +type contentFetchedMsg struct { + title string + content string + hints []string + err error +} + +func NewNote(path string) Model { + return Model{ + path: path, + loading: true, + } +} + +func (m Model) Init() tea.Cmd { + return fetchContent(m.path) +} + +func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case contentFetchedMsg: + m.loading = false + m.title = msg.title + m.content = msg.content + m.hints = msg.hints + m.err = msg.err + return m, nil + } + return m, nil +} + +func (m Model) View() string { + if m.loading { + return "Loading note..." + } + + if m.err != nil { + return "Error: " + m.err.Error() + } + + var sb strings.Builder + sb.WriteString(m.title) + sb.WriteString("\n\n") + sb.WriteString(m.content) + + if len(m.hints) > 0 { + sb.WriteString("\n\nHints:\n") + for _, hint := range m.hints { + sb.WriteString("- ") + sb.WriteString(hint) + sb.WriteString("\n") + } + } + + return sb.String() +} + +func fetchContent(path string) tea.Cmd { + return func() tea.Msg { + data, err := os.ReadFile(path) + if err != nil { + return contentFetchedMsg{err: err} + } + + content := string(data) + lines := strings.Split(content, "\n") + + var title string + + // tit;e + if len(lines) > 0 && strings.HasPrefix(lines[0], "# ") { + title = strings.TrimPrefix(lines[0], "# ") + content = strings.Join(lines[1:], "\n") + } + + // hints + hints := extractHints(content) + content = strings.TrimSpace(content) + + return contentFetchedMsg{ + title: title, + content: content, + hints: hints, + } + } +} + +func extractHints(content string) []string { + hints := make([]string, 0) + return hints // to add later +}