mirror of
https://github.com/charmbracelet/glow
synced 2024-11-10 06:04:18 +00:00
chore: use proposed api
This commit is contained in:
parent
3104f60786
commit
ab51fe2632
9 changed files with 275 additions and 201 deletions
12
go.mod
12
go.mod
|
@ -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
20
go.sum
|
@ -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=
|
||||
|
|
1
main.go
1
main.go
|
@ -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"
|
||||
|
|
28
ui/pager.go
28
ui/pager.go
|
@ -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) {
|
||||
|
|
125
ui/stash.go
125
ui/stash.go
|
@ -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("Can’t load stash") + maybeOffline
|
||||
return m.common.styles.SubtleStyle.Render("Can’t 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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
146
ui/styles.go
146
ui/styles.go
|
@ -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)"),
|
||||
}
|
||||
}
|
||||
|
|
62
ui/ui.go
62
ui/ui.go
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue