1package repo
2
3import (
4 "bytes"
5 "smoothie/git"
6 "text/template"
7
8 "github.com/charmbracelet/bubbles/viewport"
9 tea "github.com/charmbracelet/bubbletea"
10 "github.com/charmbracelet/glamour"
11)
12
13type ErrMsg struct {
14 Error error
15}
16
17type Bubble struct {
18 templateObject interface{}
19 repoSource *git.RepoSource
20 name string
21 repo *git.Repo
22 readmeViewport *ViewportBubble
23 readme string
24 height int
25 heightMargin int
26 width int
27 widthMargin int
28}
29
30func NewBubble(rs *git.RepoSource, name string, width, wm, height, hm int, tmp interface{}) *Bubble {
31 return &Bubble{
32 templateObject: tmp,
33 repoSource: rs,
34 name: name,
35 height: height,
36 width: width,
37 heightMargin: hm,
38 widthMargin: wm,
39 readmeViewport: &ViewportBubble{
40 Viewport: &viewport.Model{
41 Width: width - wm,
42 Height: height - hm,
43 },
44 },
45 }
46}
47
48func (b *Bubble) Init() tea.Cmd {
49 return b.setupCmd
50}
51
52func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
53 var cmds []tea.Cmd
54 switch msg := msg.(type) {
55 case tea.WindowSizeMsg:
56 b.readmeViewport.Viewport.Width = msg.Width - b.widthMargin
57 b.readmeViewport.Viewport.Height = msg.Height - b.heightMargin
58 md, err := b.glamourize(b.readme)
59 if err != nil {
60 return b, nil
61 }
62 b.readmeViewport.Viewport.SetContent(md)
63 }
64 rv, cmd := b.readmeViewport.Update(msg)
65 b.readmeViewport = rv.(*ViewportBubble)
66 if cmd != nil {
67 cmds = append(cmds, cmd)
68 }
69 return b, tea.Batch(cmds...)
70}
71
72func (b *Bubble) GotoTop() {
73 b.readmeViewport.Viewport.GotoTop()
74}
75
76func (b *Bubble) View() string {
77 return b.readmeViewport.View()
78}
79
80func (b *Bubble) setupCmd() tea.Msg {
81 r, err := b.repoSource.GetRepo(b.name)
82 if err == git.ErrMissingRepo {
83 return nil
84 }
85 if err != nil {
86 return ErrMsg{err}
87 }
88 md := r.Readme
89 if b.templateObject != nil {
90 md, err = b.templatize(md)
91 if err != nil {
92 return ErrMsg{err}
93 }
94 }
95 b.readme = md
96 md, err = b.glamourize(md)
97 if err != nil {
98 return ErrMsg{err}
99 }
100 b.readmeViewport.Viewport.SetContent(md)
101 b.GotoTop()
102 return nil
103}
104
105func (b *Bubble) templatize(mdt string) (string, error) {
106 t, err := template.New("readme").Parse(mdt)
107 if err != nil {
108 return "", err
109 }
110 buf := &bytes.Buffer{}
111 err = t.Execute(buf, b.templateObject)
112 if err != nil {
113 return "", err
114 }
115 return buf.String(), nil
116}
117
118func (b *Bubble) glamourize(md string) (string, error) {
119 tr, err := glamour.NewTermRenderer(
120 glamour.WithStandardStyle("dark"),
121 glamour.WithWordWrap(b.width-b.widthMargin),
122 )
123
124 if err != nil {
125 return "", err
126 }
127 mdt, err := tr.Render(md)
128 if err != nil {
129 return "", err
130 }
131 return mdt, nil
132}