1package common
2
3import (
4 "context"
5 "fmt"
6
7 "github.com/alecthomas/chroma/v2/lexers"
8 zone "github.com/aymanbagabas/bubblezone/v2"
9 "github.com/charmbracelet/log"
10 "github.com/charmbracelet/soft-serve/git"
11 "github.com/charmbracelet/soft-serve/pkg/backend"
12 "github.com/charmbracelet/soft-serve/pkg/config"
13 "github.com/charmbracelet/soft-serve/pkg/ui/keymap"
14 "github.com/charmbracelet/soft-serve/pkg/ui/styles"
15 "github.com/charmbracelet/ssh"
16)
17
18type contextKey struct {
19 name string
20}
21
22// Keys to use for context.Context.
23var (
24 ConfigKey = &contextKey{"config"}
25 RepoKey = &contextKey{"repo"}
26)
27
28// Common is a struct all components should embed.
29type Common struct {
30 ctx context.Context
31 Width, Height int
32 Styles *styles.Styles
33 KeyMap *keymap.KeyMap
34 Zone *zone.Manager
35 Logger *log.Logger
36 HideCloneCmd bool
37}
38
39// NewCommon returns a new Common struct.
40func NewCommon(ctx context.Context, width, height int) Common {
41 if ctx == nil {
42 ctx = context.TODO()
43 }
44 return Common{
45 ctx: ctx,
46 Width: width,
47 Height: height,
48 Styles: styles.DefaultStyles(),
49 KeyMap: keymap.DefaultKeyMap(),
50 Zone: zone.New(),
51 Logger: log.FromContext(ctx).WithPrefix("ui"),
52 }
53}
54
55// SetValue sets a value in the context.
56func (c *Common) SetValue(key, value interface{}) {
57 c.ctx = context.WithValue(c.ctx, key, value)
58}
59
60// SetSize sets the width and height of the common struct.
61func (c *Common) SetSize(width, height int) {
62 c.Width = width
63 c.Height = height
64}
65
66// Context returns the context.
67func (c *Common) Context() context.Context {
68 return c.ctx
69}
70
71// Config returns the server config.
72func (c *Common) Config() *config.Config {
73 return config.FromContext(c.ctx)
74}
75
76// Backend returns the Soft Serve backend.
77func (c *Common) Backend() *backend.Backend {
78 return backend.FromContext(c.ctx)
79}
80
81// Repo returns the repository.
82func (c *Common) Repo() *git.Repository {
83 v := c.ctx.Value(RepoKey)
84 if r, ok := v.(*git.Repository); ok {
85 return r
86 }
87 return nil
88}
89
90// PublicKey returns the public key.
91func (c *Common) PublicKey() ssh.PublicKey {
92 v := c.ctx.Value(ssh.ContextKeyPublicKey)
93 if p, ok := v.(ssh.PublicKey); ok {
94 return p
95 }
96 return nil
97}
98
99// CloneCmd returns the clone command string.
100func (c *Common) CloneCmd(publicURL, name string) string {
101 if c.HideCloneCmd {
102 return ""
103 }
104 return fmt.Sprintf("git clone %s", RepoURL(publicURL, name))
105}
106
107// IsFileMarkdown returns true if the file is markdown.
108// It uses chroma lexers to analyze and determine the language.
109func IsFileMarkdown(content, ext string) bool {
110 var lang string
111 lexer := lexers.Match(ext)
112 if lexer == nil {
113 lexer = lexers.Analyse(content)
114 }
115 if lexer != nil && lexer.Config() != nil {
116 lang = lexer.Config().Name
117 }
118 return lang == "markdown"
119}