chore: use proposed api

This commit is contained in:
Ayman Bagabas 2024-05-13 17:01:14 -04:00
parent 3104f60786
commit ab51fe2632
No known key found for this signature in database
GPG key ID: C8D51D2157C919AC
9 changed files with 275 additions and 201 deletions

12
go.mod
View file

@ -4,11 +4,11 @@ go 1.18
require (
github.com/atotto/clipboard v0.1.4
github.com/charmbracelet/bubbles v0.18.1-0.20240513171522-f4f674440a65
github.com/charmbracelet/bubbletea v0.26.3-0.20240510203954-a434f25ff7d3
github.com/charmbracelet/bubbles v0.18.1-0.20240513205629-dab412b45aa1
github.com/charmbracelet/bubbletea v0.26.3-0.20240513205551-cf6db9e1506a
github.com/charmbracelet/charm v0.8.7
github.com/charmbracelet/glamour v0.6.0
github.com/charmbracelet/lipgloss v0.10.1-0.20240510203806-a6dc2ab509a8
github.com/charmbracelet/lipgloss v0.10.1-0.20240513205513-d059cfa7d6f0
github.com/charmbracelet/x/editor v0.0.0-20231116172829-450eedbca1ab
github.com/dustin/go-humanize v1.0.1
github.com/mattn/go-runewidth v0.0.15
@ -17,7 +17,6 @@ require (
github.com/muesli/gitcha v0.2.0
github.com/muesli/go-app-paths v0.2.2
github.com/muesli/reflow v0.3.0
github.com/muesli/termenv v0.15.2
github.com/sahilm/fuzzy v0.1.1
github.com/segmentio/ksuid v1.0.4
github.com/spf13/cobra v1.8.0
@ -53,6 +52,7 @@ require (
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/sasquatch v0.0.0-20200811221207-66979d92330a // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
@ -74,3 +74,7 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace github.com/charmbracelet/bubbletea => ../bubbletea
replace github.com/charmbracelet/lipgloss => ../lipgloss

20
go.sum
View file

@ -60,12 +60,14 @@ github.com/calmh/randomart v1.1.0/go.mod h1:DQUbPVyP+7PAs21w/AnfMKG5NioxS3TbZ2F9
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/charmbracelet/bubbles v0.7.5/go.mod h1:IRTORFvhEI6OUH7WhN2Ks8Z8miNGimk1BE6cmHijOkM=
github.com/charmbracelet/bubbles v0.18.1-0.20240513171522-f4f674440a65 h1:dtKXN44T1Cr81tXyto7HlAg/WXp5/w/r4l7EVlrLH3A=
github.com/charmbracelet/bubbles v0.18.1-0.20240513171522-f4f674440a65/go.mod h1:zOuREWAmYnZw3MIahm43VN7IkQEIQc+Lzn7u6OO5MHo=
github.com/charmbracelet/bubbles v0.18.1-0.20240513203235-56c40cbccc32 h1:zjuJv7tymyivNHrHvT8fm25znb2TLKpxEtNxVCnIlys=
github.com/charmbracelet/bubbles v0.18.1-0.20240513203235-56c40cbccc32/go.mod h1:qUvOZdUERUQFIzbNf7A7wOO0T467L9xw7x8yIYioBu4=
github.com/charmbracelet/bubbles v0.18.1-0.20240513205629-dab412b45aa1 h1:s1XBf/Kmu+Bo3giU0yq8dtrRon0nU9Aa7W55MnpyKyQ=
github.com/charmbracelet/bubbles v0.18.1-0.20240513205629-dab412b45aa1/go.mod h1:rB0bt1GJpY/UgUubN2hkaG6ZiPBKtI7tv6cyp2eQSfY=
github.com/charmbracelet/bubbletea v0.12.2/go.mod h1:3gZkYELUOiEUOp0bTInkxguucy/xRbGSOcbMs1geLxg=
github.com/charmbracelet/bubbletea v0.23.2/go.mod h1:FaP3WUivcTM0xOKNmhciz60M6I+weYLF76mr1JyI7sM=
github.com/charmbracelet/bubbletea v0.26.3-0.20240510203954-a434f25ff7d3 h1:Bg0eRBAgsWh84rpAq5X+e52TMAfloxoWeSJkYp9Pyw0=
github.com/charmbracelet/bubbletea v0.26.3-0.20240510203954-a434f25ff7d3/go.mod h1:jxN9TKmttdNsUKWSjjQQonHIY4nCuTBNdkDn3/Bpf7A=
github.com/charmbracelet/bubbletea v0.26.3-0.20240513203730-1ef18e60b708 h1:RggxF6hXLvOAayLXBpAruL4YF3epdNj2Gs4w6piT8WM=
github.com/charmbracelet/bubbletea v0.26.3-0.20240513203730-1ef18e60b708/go.mod h1:jxN9TKmttdNsUKWSjjQQonHIY4nCuTBNdkDn3/Bpf7A=
github.com/charmbracelet/charm v0.8.7 h1:FJ9b7IxWUWHOPR72zS/QJLEqtudOB2Mwfc+Sir0eZR8=
github.com/charmbracelet/charm v0.8.7/go.mod h1:ApJYwJljEjODkOYJgFDzbUqztLrCWQct9zyPD+xcVr4=
github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc=
@ -167,6 +169,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@ -355,6 +358,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.5.2 h1:ALmeCk/px5FSm1MAcFBAsVKZjDuMVj8Tm7FFIlMJnqU=
github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
@ -379,6 +383,7 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
@ -393,6 +398,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -416,6 +422,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -450,6 +457,7 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
@ -472,6 +480,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
@ -519,6 +528,8 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -590,6 +601,7 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View file

@ -15,7 +15,6 @@ import (
"github.com/charmbracelet/glamour"
"github.com/charmbracelet/glow/ui"
"github.com/charmbracelet/glow/utils"
_ "github.com/charmbracelet/lipgloss/defaults" // Use std input defaults for lipgloss
"github.com/meowgorithm/babyenv"
gap "github.com/muesli/go-app-paths"
"github.com/spf13/cobra"

View file

@ -138,12 +138,12 @@ type pagerModel struct {
func newPagerModel(common *commonModel) pagerModel {
// Init viewport
vp := viewport.New(0, 0)
vp := viewport.New(common.ctx, 0, 0)
vp.YPosition = 0
vp.HighPerformanceRendering = config.HighPerformancePager
// Text input for notes/memos
ti := textinput.New()
ti := textinput.New(common.ctx)
ti.Prompt = " > "
ti.PromptStyle = pagerNoteInputPromptStyle
ti.TextStyle = pagerNoteInputStyle
@ -152,7 +152,7 @@ func newPagerModel(common *commonModel) pagerModel {
ti.Focus()
// Text input for search
sp := spinner.New()
sp := spinner.New(common.ctx)
sp.Style = spinnerStyle
return pagerModel{
@ -219,7 +219,7 @@ func (m *pagerModel) unload() {
m.textInput.Reset()
}
func (m pagerModel) update(msg tea.Msg) (pagerModel, tea.Cmd) {
func (m pagerModel) update(ctx tea.Context, msg tea.Msg) (pagerModel, tea.Cmd) {
var (
cmd tea.Cmd
cmds []tea.Cmd
@ -339,7 +339,7 @@ func (m pagerModel) update(msg tea.Msg) (pagerModel, tea.Cmd) {
// full lifetime. In either case we need to spin the spinner
// irrespective of it's more fine-grained visibility rules.
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
m.spinner, cmd = m.spinner.Update(ctx, msg)
cmds = append(cmds, cmd)
} else if m.state == pagerStateStashSuccess {
// Successful stash. Stop spinning and update accordingly.
@ -396,10 +396,10 @@ func (m pagerModel) update(msg tea.Msg) (pagerModel, tea.Cmd) {
switch m.state {
case pagerStateSetNote:
m.textInput, cmd = m.textInput.Update(msg)
m.textInput, cmd = m.textInput.Update(ctx, msg)
cmds = append(cmds, cmd)
default:
m.viewport, cmd = m.viewport.Update(msg)
m.viewport, cmd = m.viewport.Update(ctx, msg)
cmds = append(cmds, cmd)
}
@ -414,16 +414,16 @@ func (m pagerModel) spinnerVisible() bool {
return now.After(windowStart) && now.Before(windowEnd)
}
func (m pagerModel) View() string {
func (m pagerModel) View(ctx tea.Context) string {
var b strings.Builder
fmt.Fprint(&b, m.viewport.View()+"\n")
fmt.Fprint(&b, m.viewport.View(ctx)+"\n")
// Footer
switch m.state {
case pagerStateSetNote:
m.setNoteView(&b)
default:
m.statusBarView(&b)
m.statusBarView(ctx, &b)
}
if m.showHelp {
@ -433,7 +433,7 @@ func (m pagerModel) View() string {
return b.String()
}
func (m pagerModel) statusBarView(b *strings.Builder) {
func (m pagerModel) statusBarView(ctx tea.Context, b *strings.Builder) {
const (
minPercent float64 = 0.0
maxPercent float64 = 1.0
@ -444,7 +444,7 @@ func (m pagerModel) statusBarView(b *strings.Builder) {
showStatusMessage := m.state == pagerStateStatusMessage
// Logo
logo := glowLogoView(" Glow ")
logo := m.common.styles.LogoStyle.Render(" Glow ")
// Scroll percent
percent := math.Max(minPercent, math.Min(maxPercent, m.viewport.ScrollPercent()))
@ -468,7 +468,7 @@ func (m pagerModel) statusBarView(b *strings.Builder) {
if m.state == pagerStateStashing || m.state == pagerStateStashSuccess {
var spinner string
if m.spinnerVisible() {
spinner = m.spinner.View()
spinner = m.spinner.View(ctx)
}
statusIndicator = statusBarNoteStyle(" ") + spinner
} else if isStashed && showStatusMessage {
@ -528,7 +528,7 @@ func (m pagerModel) statusBarView(b *strings.Builder) {
func (m pagerModel) setNoteView(b *strings.Builder) {
fmt.Fprint(b, noteHeading)
fmt.Fprint(b, m.textInput.View())
fmt.Fprint(b, m.textInput.View(m.common.ctx))
}
func (m pagerModel) helpView() (s string) {

View file

@ -14,7 +14,6 @@ import (
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/charm"
"github.com/charmbracelet/lipgloss"
"github.com/muesli/reflow/ansi"
"github.com/muesli/reflow/truncate"
"github.com/sahilm/fuzzy"
@ -33,26 +32,6 @@ var (
alreadyStashedStatusMessage = statusMessage{subtleStatusMessage, "Already stashed"}
)
var (
dividerDot = darkGrayFg.SetString(" • ")
dividerBar = darkGrayFg.SetString(" │ ")
offlineHeaderNote = darkGrayFg.SetString("(Offline)")
logoStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("#ECFD65")).
Background(fuchsia).
Bold(true)
stashSpinnerStyle = lipgloss.NewStyle().
Foreground(gray)
stashInputPromptStyle = lipgloss.NewStyle().
Foreground(yellowGreen).
MarginRight(1)
stashInputCursorStyle = lipgloss.NewStyle().
Foreground(fuchsia).
MarginRight(1)
)
// MSG
type (
@ -134,41 +113,41 @@ type statusMessage struct {
message string
}
func initSections() {
func initSections(c *commonModel) {
sections = map[sectionKey]section{
localSection: {
key: localSection,
docTypes: NewDocTypeSet(LocalDoc),
paginator: newStashPaginator(),
paginator: newStashPaginator(c),
},
stashedSection: {
key: stashedSection,
docTypes: NewDocTypeSet(StashedDoc, ConvertedDoc),
paginator: newStashPaginator(),
paginator: newStashPaginator(c),
},
newsSection: {
key: newsSection,
docTypes: NewDocTypeSet(NewsDoc),
paginator: newStashPaginator(),
paginator: newStashPaginator(c),
},
filterSection: {
key: filterSection,
docTypes: DocTypeSet{},
paginator: newStashPaginator(),
paginator: newStashPaginator(c),
},
}
}
// String returns a styled version of the status message appropriate for the
// Render returns a styled version of the status message appropriate for the
// given context.
func (s statusMessage) String() string {
func (s statusMessage) Render(st *styles) string {
switch s.status {
case subtleStatusMessage:
return dimGreenFg(s.message)
return st.DimGreenFg(s.message)
case errorStatusMessage:
return redFg(s.message)
return st.RedFg(s.message)
default:
return greenFg(s.message)
return st.GreenFg(s.message)
}
}
@ -514,21 +493,21 @@ func (m *stashModel) moveCursorDown() {
// INIT
func newStashModel(common *commonModel) stashModel {
sp := spinner.New()
sp := spinner.New(common.ctx)
sp.Spinner = spinner.Line
sp.Style = stashSpinnerStyle
sp.Style = common.styles.StashSpinnerStyle
ni := textinput.New()
ni := textinput.New(common.ctx)
ni.Prompt = "Memo:"
ni.PromptStyle = stashInputPromptStyle
ni.CursorStyle = stashInputCursorStyle
ni.PromptStyle = common.styles.StashInputPromptStyle
ni.CursorStyle = common.styles.StashInputCursorStyle
ni.CharLimit = noteCharacterLimit
ni.Focus()
si := textinput.New()
si := textinput.New(common.ctx)
si.Prompt = "Find:"
si.PromptStyle = stashInputPromptStyle
si.CursorStyle = stashInputCursorStyle
si.PromptStyle = common.styles.StashInputPromptStyle
si.CursorStyle = common.styles.StashInputCursorStyle
si.CharLimit = noteCharacterLimit
si.Focus()
@ -563,17 +542,17 @@ func newStashModel(common *commonModel) stashModel {
return m
}
func newStashPaginator() paginator.Model {
p := paginator.New()
func newStashPaginator(common *commonModel) paginator.Model {
p := paginator.New(common.ctx)
p.Type = paginator.Dots
p.ActiveDot = brightGrayFg("•")
p.InactiveDot = darkGrayFg.Render("•")
p.ActiveDot = common.styles.BrightGrayFg("•")
p.InactiveDot = common.styles.DarkGrayFg("•")
return p
}
// UPDATE
func (m stashModel) update(msg tea.Msg) (stashModel, tea.Cmd) {
func (m stashModel) update(ctx tea.Context, msg tea.Msg) (stashModel, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
@ -651,7 +630,7 @@ func (m stashModel) update(msg tea.Msg) (stashModel, tea.Cmd) {
case spinner.TickMsg:
if m.shouldSpin() {
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
m.spinner, cmd = m.spinner.Update(ctx, msg)
cmds = append(cmds, cmd)
}
@ -919,7 +898,7 @@ func (m *stashModel) handleDocumentBrowsing(msg tea.Msg) tea.Cmd {
// Update paginator. Pagination key handling is done here, but it could
// also be moved up to this level, in which case we'd use model methods
// like model.PageUp().
newPaginatorModel, cmd := m.paginator().Update(msg)
newPaginatorModel, cmd := m.paginator().Update(m.common.ctx, msg)
m.setPaginator(newPaginatorModel)
cmds = append(cmds, cmd)
@ -1071,7 +1050,7 @@ func (m *stashModel) handleFiltering(msg tea.Msg) tea.Cmd {
}
// Update the filter text input component
newFilterInputModel, inputCmd := m.filterInput.Update(msg)
newFilterInputModel, inputCmd := m.filterInput.Update(m.common.ctx, msg)
currentFilterVal := m.filterInput.Value()
newFilterVal := newFilterInputModel.Value()
m.filterInput = newFilterInputModel
@ -1128,7 +1107,7 @@ func (m *stashModel) handleNoteInput(msg tea.Msg) tea.Cmd {
}
// Update the note text input component
newNoteInputModel, noteInputCmd := m.noteInput.Update(msg)
newNoteInputModel, noteInputCmd := m.noteInput.Update(m.common.ctx, msg)
m.noteInput = newNoteInputModel
cmds = append(cmds, noteInputCmd)
@ -1137,26 +1116,26 @@ func (m *stashModel) handleNoteInput(msg tea.Msg) tea.Cmd {
// VIEW
func (m stashModel) view() string {
func (m stashModel) view(ctx tea.Context) string {
var s string
switch m.viewState {
case stashStateShowingError:
return errorView(m.err, false)
return errorView(&m.common.styles, m.err, false)
case stashStateLoadingDocument:
s += " " + m.spinner.View() + " Loading document..."
s += " " + m.spinner.View(ctx) + " Loading document..."
case stashStateReady:
loadingIndicator := " "
if m.shouldSpin() {
loadingIndicator = m.spinner.View()
loadingIndicator = m.spinner.View(ctx)
}
var header string
switch m.selectionState {
case selectionPromptingDelete:
header = redFg("Delete this item from your stash? ") + faintRedFg("(y/N)")
header = m.common.styles.RedFg("Delete this item from your stash? ") + m.common.styles.FaintRedFg("(y/N)")
case selectionSettingNote:
header = yellowFg("Set the memo for this item?")
header = m.common.styles.YellowFg("Set the memo for this item?")
}
// Only draw the normal header if we're not using the header area for
@ -1168,13 +1147,13 @@ func (m stashModel) view() string {
// Rules for the logo, filter and status message.
logoOrFilter := " "
if m.showStatusMessage && m.filterState == filtering {
logoOrFilter += m.statusMessage.String()
logoOrFilter += m.statusMessage.Render(&m.common.styles)
} else if m.filterState == filtering {
logoOrFilter += m.filterInput.View()
logoOrFilter += m.filterInput.View(ctx)
} else {
logoOrFilter += glowLogoView(" Glow ")
logoOrFilter += m.common.styles.LogoStyle.Render(" Glow ")
if m.showStatusMessage {
logoOrFilter += " " + m.statusMessage.String()
logoOrFilter += " " + m.statusMessage.Render(&m.common.styles)
}
}
logoOrFilter = truncate.StringWithTail(logoOrFilter, uint(m.common.width-1), ellipsis)
@ -1195,7 +1174,7 @@ func (m stashModel) view() string {
var pagination string
if m.paginator().TotalPages > 1 {
pagination = m.paginator().View()
pagination = m.paginator().View(ctx)
// If the dot pagination is wider than the width of the window
// use the arabic paginator.
@ -1210,7 +1189,7 @@ func (m stashModel) view() string {
// pointers in our model should be refactored away.
var p paginator.Model = *(m.paginator())
p.Type = paginator.Arabic
pagination = paginationStyle.Render(p.View())
pagination = m.common.styles.PaginationStyle.Render(p.View(ctx))
}
// We could also look at m.stashFullyLoaded and add an indicator
@ -1232,10 +1211,6 @@ func (m stashModel) view() string {
return "\n" + indent(s, stashIndent)
}
func glowLogoView(text string) string {
return logoStyle.Render(text)
}
func (m stashModel) headerView() string {
localCount := m.countMarkdowns(LocalDoc)
stashedCount := m.countMarkdowns(StashedDoc) + m.countMarkdowns(ConvertedDoc)
@ -1246,7 +1221,7 @@ func (m stashModel) headerView() string {
// Filter results
if m.filterState == filtering {
if localCount+stashedCount+newsCount == 0 {
return grayFg("Nothing found.")
return m.common.styles.GrayFg("Nothing found.")
}
if localCount > 0 {
sections = append(sections, fmt.Sprintf("%d local", localCount))
@ -1256,22 +1231,22 @@ func (m stashModel) headerView() string {
}
for i := range sections {
sections[i] = grayFg(sections[i])
sections[i] = m.common.styles.GrayFg(sections[i])
}
return strings.Join(sections, dividerDot.String())
return strings.Join(sections, m.common.styles.DividerDot)
}
if m.loadingDone() && len(m.markdowns) == 0 {
var maybeOffline string
if m.common.authStatus == authFailed {
maybeOffline = " " + offlineHeaderNote.String()
maybeOffline = " " + m.common.styles.OfflineHeaderNote
}
if m.stashedOnly() {
return subtleStyle.Render("Cant load stash") + maybeOffline
return m.common.styles.SubtleStyle.Render("Cant load stash") + maybeOffline
}
return subtleStyle.Render("No markdown files found") + maybeOffline
return m.common.styles.SubtleStyle.Render("No markdown files found") + maybeOffline
}
// Tabs
@ -1299,16 +1274,16 @@ func (m stashModel) headerView() string {
}
if m.sectionIndex == i && len(m.sections) > 1 {
s = selectedTabStyle.Render(s)
s = m.common.styles.SelectedTabStyle.Render(s)
} else {
s = tabStyle.Render(s)
s = m.common.styles.TabStyle.Render(s)
}
sections = append(sections, s)
}
s := strings.Join(sections, dividerBar.String())
s := strings.Join(sections, m.common.styles.DividerBar)
if m.common.authStatus == authFailed {
s += dividerDot.String() + offlineHeaderNote.String()
s += m.common.styles.DividerDot + m.common.styles.OfflineHeaderNote
}
return s
@ -1322,7 +1297,7 @@ func (m stashModel) populatedView() string {
// Empty states
if len(mds) == 0 {
f := func(s string) {
b.WriteString(" " + grayFg(s))
b.WriteString(" " + m.common.styles.GrayFg(s))
}
switch m.sections[m.sectionIndex].key {

View file

@ -30,7 +30,7 @@ func newHelpColumn(pairs ...string) (h helpColumn) {
}
// render returns styled and formatted rows from keys and values.
func (h helpColumn) render(height int) (rows []string) {
func (h helpColumn) render(st *styles, height int) (rows []string) {
keyWidth, valWidth := h.maxWidths()
for i := 0; i < height; i++ {
@ -44,11 +44,11 @@ func (h helpColumn) render(height int) (rows []string) {
switch k {
case "s":
k = greenFg(k)
v = semiDimGreenFg(v)
k = st.GreenFg(k)
v = st.SemiDimGreenFg(v)
default:
k = grayFg(k)
v = midGrayFg(v)
k = st.GrayFg(k)
v = st.MidGrayFg(v)
}
}
b.WriteString(k)
@ -196,12 +196,13 @@ func (m stashModel) renderHelp(groups ...[]string) (string, int) {
// would otherwise wrap to two lines. Help view entries should come in as pairs,
// with the first being the key and the second being the help text.
func (m stashModel) miniHelpView(entries ...string) string {
st := &m.common.styles
if len(entries) == 0 {
return ""
}
var (
truncationChar = subtleStyle.Render("…")
truncationChar = st.SubtleStyle.Render("…")
truncationWidth = ansi.PrintableRuneWidth(truncationChar)
)
@ -221,17 +222,17 @@ func (m stashModel) miniHelpView(entries ...string) string {
switch k {
case "s":
k = greenFg(k)
v = semiDimGreenFg(v)
k = st.GreenFg(k)
v = st.SemiDimGreenFg(v)
default:
k = grayFg(k)
v = midGrayFg(v)
k = st.GrayFg(k)
v = st.MidGrayFg(v)
}
next = fmt.Sprintf("%s %s", k, v)
if i < len(entries)-2 {
next += dividerDot.String()
next += st.DividerDot
}
// Only this (and the following) help text items if we have the
@ -269,7 +270,7 @@ func (m stashModel) fullHelpView(groups ...[]string) string {
// Build columns
for _, c := range columns {
renderedCols = append(renderedCols, c.render(tallestCol))
renderedCols = append(renderedCols, c.render(&m.common.styles, tallestCol))
}
// Merge columns

View file

@ -46,6 +46,7 @@ func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) {
isSelected := index == m.cursor()
isFiltering := m.filterState == filtering
singleFilteredItem := isFiltering && len(m.getVisibleMarkdowns()) == 1
styles := &m.common.styles
// If there are multiple items being filtered don't highlight a selected
// item in the results. If we've filtered down to one item, however,
@ -55,33 +56,33 @@ func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) {
switch m.selectionState {
case selectionPromptingDelete:
gutter = faintRedFg(verticalLine)
icon = faintRedFg(icon)
title = redFg(title)
date = faintRedFg(date)
gutter = styles.FaintRedFg(verticalLine)
icon = styles.FaintRedFg(icon)
title = styles.RedFg(title)
date = styles.FaintRedFg(date)
case selectionSettingNote:
gutter = dullYellowFg(verticalLine)
gutter = styles.DullYellowFg(verticalLine)
icon = ""
title = m.noteInput.View()
date = dullYellowFg(date)
title = m.noteInput.View(m.common.ctx)
date = styles.DullYellowFg(date)
default:
if m.common.latestFileStashed == md.stashID &&
m.statusMessage == stashingStatusMessage {
gutter = greenFg(verticalLine)
icon = dimGreenFg(icon)
title = greenFg(title)
date = semiDimGreenFg(date)
gutter = styles.GreenFg(verticalLine)
icon = styles.DimGreenFg(icon)
title = styles.GreenFg(title)
date = styles.SemiDimGreenFg(date)
} else {
gutter = dullFuchsiaFg(verticalLine)
icon = dullFuchsiaFg(icon)
gutter = styles.DullFuchsiaFg(verticalLine)
icon = styles.DullFuchsiaFg(icon)
if m.currentSection().key == filterSection &&
m.filterState == filterApplied || singleFilteredItem {
s := lipgloss.NewStyle().Foreground(fuchsia)
title = styleFilteredText(title, m.filterInput.Value(), s, s.Copy().Underline(true))
} else {
title = fuchsiaFg(title)
title = styles.FuchsiaFg(title)
}
date = dullFuchsiaFg(date)
date = styles.DullFuchsiaFg(date)
}
}
} else {
@ -91,35 +92,35 @@ func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) {
if m.common.latestFileStashed == md.stashID &&
m.statusMessage == stashingStatusMessage {
icon = dimGreenFg(icon)
title = greenFg(title)
date = semiDimGreenFg(date)
icon = styles.DimGreenFg(icon)
title = styles.GreenFg(title)
date = styles.SemiDimGreenFg(date)
} else if md.docType == NewsDoc {
if isFiltering && m.filterInput.Value() == "" {
title = dimIndigoFg(title)
date = dimSubtleIndigoFg(date)
title = styles.DimIndigoFg(title)
date = styles.DimSubtleIndigoFg(date)
} else {
s := lipgloss.NewStyle().Foreground(indigo)
title = styleFilteredText(title, m.filterInput.Value(), s, s.Copy().Underline(true))
date = subtleIndigoFg(date)
date = styles.SubtleIndigoFg(date)
}
} else if isFiltering && m.filterInput.Value() == "" {
icon = dimGreenFg(icon)
icon = styles.DimGreenFg(icon)
if title == noMemoTitle {
title = dimBrightGrayFg(title)
title = styles.DimBrightGrayFg(title)
} else {
title = dimNormalFg(title)
title = styles.DimNormalFg(title)
}
date = dimBrightGrayFg(date)
date = styles.DimBrightGrayFg(date)
} else {
icon = greenFg(icon)
icon = styles.GreenFg(icon)
if title == noMemoTitle {
title = brightGrayFg(title)
title = styles.BrightGrayFg(title)
} else {
s := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#1a1a1a", Dark: "#dddddd"})
title = styleFilteredText(title, m.filterInput.Value(), s, s.Copy().Underline(true))
}
date = brightGrayFg(date)
date = styles.BrightGrayFg(date)
}
}

View file

@ -1,6 +1,10 @@
package ui
import . "github.com/charmbracelet/lipgloss" //nolint: revive
import (
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
. "github.com/charmbracelet/lipgloss"
) //nolint: revive
// Colors.
var (
@ -30,55 +34,125 @@ var (
dimGreen = AdaptiveColor{Light: "#72D2B0", Dark: "#0B5137"}
)
type styler func(...string) string
// Ulimately, we'll transition to named styles.
// nolint:deadcode,unused,varcheck
var (
normalFg = NewStyle().Foreground(normal).Render
dimNormalFg = NewStyle().Foreground(normalDim).Render
type styles struct {
NormalFg styler
DimNormalFg styler
brightGrayFg = NewStyle().Foreground(brightGray).Render
dimBrightGrayFg = NewStyle().Foreground(dimBrightGray).Render
BrightGrayFg styler
DimBrightGrayFg styler
grayFg = NewStyle().Foreground(gray).Render
midGrayFg = NewStyle().Foreground(midGray).Render
darkGrayFg = NewStyle().Foreground(darkGray)
GrayFg styler
MidGrayFg styler
DarkGrayFg styler
greenFg = NewStyle().Foreground(green).Render
semiDimGreenFg = NewStyle().Foreground(semiDimGreen).Render
dimGreenFg = NewStyle().Foreground(dimGreen).Render
GreenFg styler
SemiDimGreenFg styler
DimGreenFg styler
fuchsiaFg = NewStyle().Foreground(fuchsia).Render
dimFuchsiaFg = NewStyle().Foreground(dimFuchsia).Render
FuchsiaFg styler
DimFuchsiaFg styler
dullFuchsiaFg = NewStyle().Foreground(dullFuchsia).Render
dimDullFuchsiaFg = NewStyle().Foreground(dimDullFuchsia).Render
DullFuchsiaFg styler
DimDullFuchsiaFg styler
indigoFg = NewStyle().Foreground(fuchsia).Render
dimIndigoFg = NewStyle().Foreground(dimIndigo).Render
IndigoFg styler
DimIndigoFg styler
subtleIndigoFg = NewStyle().Foreground(subtleIndigo).Render
dimSubtleIndigoFg = NewStyle().Foreground(dimSubtleIndigo).Render
SubtleIndigoFg styler
DimSubtleIndigoFg styler
yellowFg = NewStyle().Foreground(yellowGreen).Render // renders light green on light backgrounds
dullYellowFg = NewStyle().Foreground(dullYellowGreen).Render // renders light green on light backgrounds
redFg = NewStyle().Foreground(red).Render
faintRedFg = NewStyle().Foreground(faintRed).Render
)
YellowFg styler
DullYellowFg styler
RedFg styler
FaintRedFg styler
var (
tabStyle = NewStyle().
Foreground(AdaptiveColor{Light: "#909090", Dark: "#626262"})
TabStyle Style
SelectedTabStyle Style
ErrorTitleStyle Style
SubtleStyle Style
PaginationStyle Style
selectedTabStyle = NewStyle().
Foreground(AdaptiveColor{Light: "#333333", Dark: "#979797"})
LogoStyle Style
StashSpinnerStyle Style
StashInputPromptStyle Style
StashInputCursorStyle Style
errorTitleStyle = NewStyle().
DividerDot string
DividerBar string
OfflineHeaderNote string
}
func defaultStyles(ctx tea.Context) styles {
darkGrayFg := ctx.NewStyle().Foreground(darkGray).Render
subtleStyle := ctx.NewStyle().
Foreground(AdaptiveColor{Light: "#9B9B9B", Dark: "#5C5C5C"})
return styles{
NormalFg: ctx.NewStyle().Foreground(normal).Render,
DimNormalFg: ctx.NewStyle().Foreground(normalDim).Render,
BrightGrayFg: ctx.NewStyle().Foreground(brightGray).Render,
DimBrightGrayFg: ctx.NewStyle().Foreground(dimBrightGray).Render,
GrayFg: ctx.NewStyle().Foreground(gray).Render,
MidGrayFg: ctx.NewStyle().Foreground(midGray).Render,
DarkGrayFg: darkGrayFg,
GreenFg: ctx.NewStyle().Foreground(green).Render,
SemiDimGreenFg: ctx.NewStyle().Foreground(semiDimGreen).Render,
DimGreenFg: ctx.NewStyle().Foreground(dimGreen).Render,
FuchsiaFg: ctx.NewStyle().Foreground(fuchsia).Render,
DimFuchsiaFg: ctx.NewStyle().Foreground(dimFuchsia).Render,
DullFuchsiaFg: ctx.NewStyle().Foreground(dullFuchsia).Render,
DimDullFuchsiaFg: ctx.NewStyle().Foreground(dimDullFuchsia).Render,
IndigoFg: ctx.NewStyle().Foreground(fuchsia).Render,
DimIndigoFg: ctx.NewStyle().Foreground(dimIndigo).Render,
SubtleIndigoFg: ctx.NewStyle().Foreground(subtleIndigo).Render,
DimSubtleIndigoFg: ctx.NewStyle().Foreground(dimSubtleIndigo).Render,
YellowFg: ctx.NewStyle().Foreground(yellowGreen).Render, // renders light green on light backgrounds
DullYellowFg: ctx.NewStyle().Foreground(dullYellowGreen).Render, // renders light green on light backgrounds
RedFg: ctx.NewStyle().Foreground(red).Render,
FaintRedFg: ctx.NewStyle().Foreground(faintRed).Render,
TabStyle: ctx.NewStyle().
Foreground(AdaptiveColor{Light: "#909090", Dark: "#626262"}),
SelectedTabStyle: ctx.NewStyle().
Foreground(AdaptiveColor{Light: "#333333", Dark: "#979797"}),
ErrorTitleStyle: ctx.NewStyle().
Foreground(cream).
Background(red).
Padding(0, 1)
Padding(0, 1),
subtleStyle = NewStyle().
Foreground(AdaptiveColor{Light: "#9B9B9B", Dark: "#5C5C5C"})
SubtleStyle: subtleStyle,
paginationStyle = subtleStyle.Copy()
)
PaginationStyle: subtleStyle.Copy(),
LogoStyle: ctx.NewStyle().
Foreground(lipgloss.Color("#ECFD65")).
Background(fuchsia).
Bold(true),
StashSpinnerStyle: ctx.NewStyle().
Foreground(gray),
StashInputPromptStyle: ctx.NewStyle().
Foreground(yellowGreen).
MarginRight(1),
StashInputCursorStyle: ctx.NewStyle().
Foreground(fuchsia).
MarginRight(1),
DividerDot: darkGrayFg(" • "),
DividerBar: darkGrayFg(" │ "),
OfflineHeaderNote: darkGrayFg("(Offline)"),
}
}

View file

@ -14,7 +14,6 @@ import (
"github.com/charmbracelet/charm/keygen"
"github.com/charmbracelet/glow/utils"
"github.com/muesli/gitcha"
te "github.com/muesli/termenv"
"github.com/segmentio/ksuid"
)
@ -141,6 +140,7 @@ const (
// Common stuff we'll need to access in all models.
type commonModel struct {
ctx tea.Context
cfg Config
cc *charm.Client
cwd string
@ -158,6 +158,8 @@ type commonModel struct {
// Files currently being stashed. We remove files from this set once
// a stash operation has either succeeded or failed.
filesStashing map[ksuid.KSUID]struct{}
styles styles
}
func (c commonModel) isStashing() bool {
@ -199,16 +201,6 @@ func (m *model) unloadDocument() []tea.Cmd {
}
func newModel(cfg Config) tea.Model {
initSections()
if cfg.GlamourStyle == "auto" {
if te.HasDarkBackground() {
cfg.GlamourStyle = "dark"
} else {
cfg.GlamourStyle = "light"
}
}
if len(cfg.DocumentTypes) == 0 {
cfg.DocumentTypes.Add(LocalDoc, StashedDoc, ConvertedDoc, NewsDoc)
}
@ -224,12 +216,28 @@ func newModel(cfg Config) tea.Model {
common: &common,
state: stateShowStash,
keygenState: keygenUnstarted,
pager: newPagerModel(&common),
stash: newStashModel(&common),
}
}
func (m model) Init(tea.Context) (tea.Model, tea.Cmd) {
func (m model) Init(ctx tea.Context) (tea.Model, tea.Cmd) {
if m.common.cfg.GlamourStyle == "auto" {
if ctx.HasLightBackground() {
m.common.cfg.GlamourStyle = "light"
} else {
m.common.cfg.GlamourStyle = "dark"
}
}
// Initialize styles & sub-models
m.common.ctx = ctx
m.common.styles = defaultStyles(ctx)
// Initialize sections after we have the styles
initSections(m.common)
m.pager = newPagerModel(m.common)
m.stash = newStashModel(m.common)
var cmds []tea.Cmd
d := m.common.cfg.DocumentTypes
@ -273,7 +281,7 @@ func (m model) Update(ctx tea.Context, msg tea.Msg) (tea.Model, tea.Cmd) {
case stateShowStash:
// pass through all keys if we're editing the filter
if m.stash.filterState == filtering || m.stash.selectionState == selectionSettingNote {
m.stash, cmd = m.stash.update(msg)
m.stash, cmd = m.stash.update(ctx, msg)
return m, cmd
}
@ -283,7 +291,7 @@ func (m model) Update(ctx tea.Context, msg tea.Msg) (tea.Model, tea.Cmd) {
// If setting a note send all keys straight through
case pagerStateSetNote:
var batch []tea.Cmd
newPagerModel, cmd := m.pager.update(msg)
newPagerModel, cmd := m.pager.update(ctx, msg)
m.pager = newPagerModel
batch = append(batch, cmd)
return m, tea.Batch(batch...)
@ -370,7 +378,7 @@ func (m model) Update(ctx tea.Context, msg tea.Msg) (tea.Model, tea.Cmd) {
// A note was saved to a document. This will have been done in the
// pager, so we'll need to find the corresponding note in the stash.
// So, pass the message to the stash for processing.
stashModel, cmd := m.stash.update(msg)
stashModel, cmd := m.stash.update(ctx, msg)
m.stash = stashModel
return m, cmd
@ -378,7 +386,7 @@ func (m model) Update(ctx tea.Context, msg tea.Msg) (tea.Model, tea.Cmd) {
// Always pass these messages to the stash so we can keep it updated
// about network activity, even if the user isn't currently viewing
// the stash.
stashModel, cmd := m.stash.update(msg)
stashModel, cmd := m.stash.update(ctx, msg)
m.stash = stashModel
return m, cmd
@ -424,7 +432,7 @@ func (m model) Update(ctx tea.Context, msg tea.Msg) (tea.Model, tea.Cmd) {
case filteredMarkdownMsg:
if m.state == stateShowDocument {
newStashModel, cmd := m.stash.update(msg)
newStashModel, cmd := m.stash.update(ctx, msg)
m.stash = newStashModel
cmds = append(cmds, cmd)
}
@ -433,12 +441,12 @@ func (m model) Update(ctx tea.Context, msg tea.Msg) (tea.Model, tea.Cmd) {
// Process children
switch m.state {
case stateShowStash:
newStashModel, cmd := m.stash.update(msg)
newStashModel, cmd := m.stash.update(ctx, msg)
m.stash = newStashModel
cmds = append(cmds, cmd)
case stateShowDocument:
newPagerModel, cmd := m.pager.update(msg)
newPagerModel, cmd := m.pager.update(ctx, msg)
m.pager = newPagerModel
cmds = append(cmds, cmd)
}
@ -448,18 +456,18 @@ func (m model) Update(ctx tea.Context, msg tea.Msg) (tea.Model, tea.Cmd) {
func (m model) View(ctx tea.Context) string {
if m.fatalErr != nil {
return errorView(m.fatalErr, true)
return errorView(&m.common.styles, m.fatalErr, true)
}
switch m.state {
case stateShowDocument:
return m.pager.View()
return m.pager.View(ctx)
default:
return m.stash.view()
return m.stash.view(ctx)
}
}
func errorView(err error, fatal bool) string {
func errorView(st *styles, err error, fatal bool) string {
exitMsg := "press any key to "
if fatal {
exitMsg += "exit"
@ -467,9 +475,9 @@ func errorView(err error, fatal bool) string {
exitMsg += "return"
}
s := fmt.Sprintf("%s\n\n%v\n\n%s",
errorTitleStyle.Render("ERROR"),
st.ErrorTitleStyle.Render("ERROR"),
err,
subtleStyle.Render(exitMsg),
st.SubtleStyle.Render(exitMsg),
)
return "\n" + indent(s, 3)
}