common.go

  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}