feat(font): cache font list

resolves #5300
This commit is contained in:
Jan De Dobbeleer 2024-07-22 08:55:11 +02:00 committed by Jan De Dobbeleer
parent 0b4a9ceb31
commit b356900c30
6 changed files with 82 additions and 4 deletions

11
.vscode/launch.json vendored
View file

@ -155,6 +155,17 @@
"upgrade" "upgrade"
] ]
}, },
{
"name": "Font install",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceRoot}/src",
"args": [
"font",
"install"
]
},
{ {
"type": "node", "type": "node",
"request": "launch", "request": "launch",

7
src/cache/cache.go vendored
View file

@ -34,6 +34,13 @@ var (
TOGGLECACHE = fmt.Sprintf("toggle_cache_%s", pid()) TOGGLECACHE = fmt.Sprintf("toggle_cache_%s", pid())
PROMPTCOUNTCACHE = fmt.Sprintf("prompt_count_cache_%s", pid()) PROMPTCOUNTCACHE = fmt.Sprintf("prompt_count_cache_%s", pid())
ENGINECACHE = fmt.Sprintf("engine_cache_%s", pid()) ENGINECACHE = fmt.Sprintf("engine_cache_%s", pid())
FONTLISTCACHE = "font_list_cache"
)
const (
ONEDAY = 1440
ONEWEEK = 10080
ONEMONTH = 43200
) )
type Entry struct { type Entry struct {

View file

@ -35,11 +35,14 @@ You can do the following:
_ = cmd.Help() _ = cmd.Help()
return return
} }
env := &runtime.Terminal{ env := &runtime.Terminal{
CmdFlags: &runtime.Flags{}, CmdFlags: &runtime.Flags{},
} }
env.Init() env.Init()
defer env.Close() defer env.Close()
switch args[0] { switch args[0] {
case "path": case "path":
fmt.Print(env.CachePath()) fmt.Print(env.CachePath())

View file

@ -35,13 +35,14 @@ This command is used to install fonts and configure the font in your terminal.
if len(args) > 1 { if len(args) > 1 {
fontName = args[1] fontName = args[1]
} }
env := &runtime.Terminal{} env := &runtime.Terminal{}
env.Init() env.Init()
defer env.Close() defer env.Close()
terminal.Init(env.Shell()) terminal.Init(env.Shell())
font.Run(fontName, env.Root()) font.Run(fontName, env)
return return
case "configure": case "configure":

View file

@ -10,10 +10,14 @@ import (
"github.com/charmbracelet/bubbles/spinner" "github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
"github.com/jandedobbeleer/oh-my-posh/src/terminal" "github.com/jandedobbeleer/oh-my-posh/src/terminal"
) )
var program *tea.Program var (
program *tea.Program
environment runtime.Environment
)
const listHeight = 14 const listHeight = 14
@ -114,6 +118,7 @@ func downloadFontZip(location string) {
program.Send(errMsg(err)) program.Send(errMsg(err))
return return
} }
program.Send(zipMsg(zipFile)) program.Send(zipMsg(zipFile))
} }
@ -123,6 +128,7 @@ func installLocalFontZIP(zipFile string, user bool) {
program.Send(errMsg(err)) program.Send(errMsg(err))
return return
} }
installFontZIP(data, user) installFontZIP(data, user)
} }
@ -132,6 +138,7 @@ func installFontZIP(zipFile []byte, user bool) {
program.Send(errMsg(err)) program.Send(errMsg(err))
return return
} }
program.Send(successMsg(families)) program.Send(successMsg(families))
} }
@ -159,6 +166,7 @@ func (m *main) Init() tea.Cmd {
} }
go getFontsList() go getFontsList()
}() }()
s := spinner.New() s := spinner.New()
s.Spinner = spinner.Dot s.Spinner = spinner.Dot
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("170")) s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("170"))
@ -167,6 +175,7 @@ func (m *main) Init() tea.Cmd {
if isLocalZipFile() { if isLocalZipFile() {
m.state = unzipFont m.state = unzipFont
} }
return m.spinner.Tick return m.spinner.Tick
} }
@ -245,6 +254,7 @@ func (m *main) View() string {
if m.err != nil { if m.err != nil {
return textStyle.Render(m.err.Error()) return textStyle.Render(m.err.Error())
} }
switch m.state { switch m.state {
case getFonts: case getFonts:
return textStyle.Render(fmt.Sprintf("%s Downloading font list%s", m.spinner.View(), terminal.StartProgress())) return textStyle.Render(fmt.Sprintf("%s Downloading font list%s", m.spinner.View(), terminal.StartProgress()))
@ -260,8 +270,10 @@ func (m *main) View() string {
return textStyle.Render(fmt.Sprintf("No need to install a new font? That's cool.%s", terminal.StopProgress())) return textStyle.Render(fmt.Sprintf("No need to install a new font? That's cool.%s", terminal.StopProgress()))
case done: case done:
var builder strings.Builder var builder strings.Builder
builder.WriteString(fmt.Sprintf("Successfully installed %s 🚀\n\n%s", m.font, terminal.StopProgress())) builder.WriteString(fmt.Sprintf("Successfully installed %s 🚀\n\n%s", m.font, terminal.StopProgress()))
builder.WriteString("The following font families are now available for configuration:\n") builder.WriteString("The following font families are now available for configuration:\n")
for i, family := range m.families { for i, family := range m.families {
builder.WriteString(fmt.Sprintf(" • %s", family)) builder.WriteString(fmt.Sprintf(" • %s", family))
@ -269,16 +281,21 @@ func (m *main) View() string {
builder.WriteString("\n") builder.WriteString("\n")
} }
} }
return textStyle.Render(builder.String()) return textStyle.Render(builder.String())
} }
return "" return ""
} }
func Run(font string, system bool) { func Run(font string, env runtime.Environment) {
main := &main{ main := &main{
font: font, font: font,
system: system, system: env.Root(),
} }
environment = env
program = tea.NewProgram(main) program = tea.NewProgram(main)
if _, err := program.Run(); err != nil { if _, err := program.Run(); err != nil {
print("Error running program: %v", err) print("Error running program: %v", err)

View file

@ -10,6 +10,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/jandedobbeleer/oh-my-posh/src/cache"
"github.com/jandedobbeleer/oh-my-posh/src/runtime/http" "github.com/jandedobbeleer/oh-my-posh/src/runtime/http"
) )
@ -26,6 +27,10 @@ type Asset struct {
func (a Asset) FilterValue() string { return a.Name } func (a Asset) FilterValue() string { return a.Name }
func Fonts() ([]*Asset, error) { func Fonts() ([]*Asset, error) {
if assets, err := getCachedFontData(); err == nil {
return assets, nil
}
assets, err := fetchFontAssets("ryanoasis/nerd-fonts") assets, err := fetchFontAssets("ryanoasis/nerd-fonts")
if err != nil { if err != nil {
return nil, err return nil, err
@ -39,9 +44,43 @@ func Fonts() ([]*Asset, error) {
assets = append(assets, cascadiaCode...) assets = append(assets, cascadiaCode...)
sort.Slice(assets, func(i, j int) bool { return assets[i].Name < assets[j].Name }) sort.Slice(assets, func(i, j int) bool { return assets[i].Name < assets[j].Name })
setCachedFontData(assets)
return assets, nil return assets, nil
} }
func getCachedFontData() ([]*Asset, error) {
if environment == nil {
return nil, errors.New("environment not set")
}
list, OK := environment.Cache().Get(cache.FONTLISTCACHE)
if !OK {
return nil, errors.New("cache not found")
}
assets := make([]*Asset, 0)
err := json.Unmarshal([]byte(list), &assets)
if err != nil {
return nil, err
}
return assets, nil
}
func setCachedFontData(assets []*Asset) {
if environment == nil {
return
}
data, err := json.Marshal(assets)
if err != nil {
return
}
environment.Cache().Set(cache.FONTLISTCACHE, string(data), cache.ONEDAY)
}
func CascadiaCode() ([]*Asset, error) { func CascadiaCode() ([]*Asset, error) {
return fetchFontAssets("microsoft/cascadia-code") return fetchFontAssets("microsoft/cascadia-code")
} }