Merge branch 'vite' of github.com:ewdieckman/oh-my-posh into vite

This commit is contained in:
Dieckman, Eric 2024-12-20 14:41:53 -06:00
commit d7e9ec5614
7 changed files with 143 additions and 65 deletions

View file

@ -14,21 +14,22 @@ func editFileWithEditor(file string) int {
return 1 return 1
} }
var args []string editor = strings.TrimSpace(editor)
if strings.Contains(editor, " ") { args := strings.Split(editor, " ")
strs := strings.Split(editor, " ")
editor = strs[0] editor = args[0]
args = strs[1:] args = append(args[1:], file)
}
args = append(args, file)
cmd := exec.Command(editor, args...) cmd := exec.Command(editor, args...)
err := cmd.Run() cmd.Stdin = os.Stdin
if err != nil { cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
return 1 return 1
} }
return cmd.ProcessState.ExitCode() return 0
} }

View file

@ -72,14 +72,13 @@ const (
) )
type main struct { type main struct {
err error err error
list *list.Model list *list.Model
font string Asset
zipFolder string families []string
families []string spinner spinner.Model
spinner spinner.Model state state
state state system bool
system bool
} }
func (m *main) buildFontList(nerdFonts []*Asset) { func (m *main) buildFontList(nerdFonts []*Asset) {
@ -122,7 +121,7 @@ func downloadFontZip(location string) {
} }
func installLocalFontZIP(m *main) { func installLocalFontZIP(m *main) {
data, err := os.ReadFile(m.font) data, err := os.ReadFile(m.URL)
if err != nil { if err != nil {
program.Send(errMsg(err)) program.Send(errMsg(err))
return return
@ -143,28 +142,48 @@ func installFontZIP(zipFile []byte, m *main) {
func (m *main) Init() tea.Cmd { func (m *main) Init() tea.Cmd {
isLocalZipFile := func() bool { isLocalZipFile := func() bool {
return !strings.HasPrefix(m.font, "https") && strings.HasSuffix(m.font, ".zip") return !strings.HasPrefix(m.URL, "https") && strings.HasSuffix(m.URL, ".zip")
} }
if len(m.font) != 0 && !isLocalZipFile() { resolveFontZipURL := func() error {
if strings.HasPrefix(m.URL, "https") {
return nil
}
fonts, err := Fonts()
if err != nil {
return err
}
var fontAsset *Asset
for _, font := range fonts {
if m.URL != font.Name {
continue
}
fontAsset = font
break
}
if fontAsset == nil {
return fmt.Errorf("no matching font found")
}
m.Asset = *fontAsset
return nil
}
if len(m.URL) != 0 && !isLocalZipFile() {
m.state = downloadFont m.state = downloadFont
if !strings.HasPrefix(m.font, "https") { if err := resolveFontZipURL(); err != nil {
if m.font == CascadiaCodeMS { m.err = err
cascadia, err := CascadiaCode() return tea.Quit
if err != nil {
m.err = err
return tea.Quit
}
m.font = cascadia.URL
} else {
m.font = fmt.Sprintf("https://github.com/ryanoasis/nerd-fonts/releases/latest/download/%s.zip", m.font)
}
} }
defer func() { defer func() {
go downloadFontZip(m.font) go downloadFontZip(m.URL)
}() }()
m.spinner.Spinner = spinner.Globe m.spinner.Spinner = spinner.Globe
@ -214,20 +233,25 @@ func (m *main) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Quit return m, tea.Quit
case "enter": case "enter":
if len(m.font) != 0 || m.list == nil || m.list.SelectedItem() == nil { if len(m.URL) != 0 || m.list == nil || m.list.SelectedItem() == nil {
return m, nil return m, nil
} }
var font *Asset var font *Asset
var ok bool var ok bool
if font, ok = m.list.SelectedItem().(*Asset); !ok { if font, ok = m.list.SelectedItem().(*Asset); !ok {
m.err = fmt.Errorf("no font selected") m.err = fmt.Errorf("no font selected")
return m, tea.Quit return m, tea.Quit
} }
m.state = downloadFont m.state = downloadFont
m.font = font.Name m.Asset = *font
defer func() { defer func() {
go downloadFontZip(font.URL) go downloadFontZip(font.URL)
}() }()
m.spinner.Spinner = spinner.Globe m.spinner.Spinner = spinner.Globe
return m, m.spinner.Tick return m, m.spinner.Tick
@ -295,11 +319,11 @@ func (m *main) View() string {
case selectFont: case selectFont:
return fmt.Sprintf("\n%s%s", m.list.View(), terminal.StopProgress()) return fmt.Sprintf("\n%s%s", m.list.View(), terminal.StopProgress())
case downloadFont: case downloadFont:
return textStyle.Render(fmt.Sprintf("%s Downloading %s%s", m.spinner.View(), m.font, terminal.StartProgress())) return textStyle.Render(fmt.Sprintf("%s Downloading %s%s", m.spinner.View(), m.Name, terminal.StartProgress()))
case unzipFont: case unzipFont:
return textStyle.Render(fmt.Sprintf("%s Extracting %s", m.spinner.View(), m.font)) return textStyle.Render(fmt.Sprintf("%s Extracting %s", m.spinner.View(), m.Name))
case installFont: case installFont:
return textStyle.Render(fmt.Sprintf("%s Installing %s", m.spinner.View(), m.font)) return textStyle.Render(fmt.Sprintf("%s Installing %s", m.spinner.View(), m.Name))
case quit: case quit:
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:
@ -309,7 +333,7 @@ func (m *main) View() string {
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.Name, terminal.StopProgress()))
builder.WriteString("The following font families are now available for configuration:\n\n") builder.WriteString("The following font families are now available for configuration:\n\n")
for i, family := range m.families { for i, family := range m.families {
@ -328,9 +352,12 @@ func (m *main) View() string {
func Run(font string, ch cache_.Cache, root bool, zipFolder string) { func Run(font string, ch cache_.Cache, root bool, zipFolder string) {
main := &main{ main := &main{
font: font, system: root,
system: root, Asset: Asset{
zipFolder: zipFolder, Name: font,
URL: font,
Folder: zipFolder,
},
} }
cache = ch cache = ch

View file

@ -10,25 +10,55 @@ import (
"io" "io"
httplib "net/http" httplib "net/http"
"net/url" "net/url"
"os"
"path"
"path/filepath"
cache_ "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"
) )
func Download(fontPath string) ([]byte, error) { func Download(fontURL string) ([]byte, error) {
u, err := url.Parse(fontPath) if zipPath, OK := cache.Get(fontURL); OK {
if b, err := os.ReadFile(zipPath); err == nil {
return b, nil
}
}
// validate if we have a local file
u, err := url.Parse(fontURL)
if err != nil || u.Scheme != "https" { if err != nil || u.Scheme != "https" {
return nil, errors.New("font path must be a valid URL") return nil, errors.New("font path must be a valid URL")
} }
var b []byte var b []byte
if b, err = getRemoteFile(fontPath); err != nil { if b, err = getRemoteFile(fontURL); err != nil {
return nil, err return nil, err
} }
if !isZipFile(b) { if !isZipFile(b) {
return nil, fmt.Errorf("%s is not a valid zip file", fontPath) return nil, fmt.Errorf("%s is not a valid zip file", fontURL)
} }
fileName := path.Base(fontURL)
zipPath := filepath.Join(os.TempDir(), fileName)
tempFile, err := os.Create(zipPath)
defer func() {
_ = tempFile.Close()
}()
if err != nil {
return b, nil
}
_, err = tempFile.Write(b)
if err != nil {
return b, nil
}
cache.Set(fontURL, zipPath, cache_.ONEDAY)
return b, nil return b, nil
} }
@ -42,10 +72,12 @@ func getRemoteFile(location string) (data []byte, err error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp, err := http.HTTPClient.Do(req) resp, err := http.HTTPClient.Do(req)
if err != nil { if err != nil {
return return
} }
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != httplib.StatusOK { if resp.StatusCode != httplib.StatusOK {

View file

@ -23,9 +23,10 @@ type release struct {
} }
type Asset struct { type Asset struct {
Name string `json:"name"` Name string `json:"name"`
URL string `json:"browser_download_url"` URL string `json:"browser_download_url"`
State string `json:"state"` State string `json:"state"`
Folder string `json:"folder"`
} }
func (a Asset) FilterValue() string { return a.Name } func (a Asset) FilterValue() string { return a.Name }
@ -42,7 +43,7 @@ func Fonts() ([]*Asset, error) {
cascadiaCode, err := CascadiaCode() cascadiaCode, err := CascadiaCode()
if err == nil { if err == nil {
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 })
@ -84,16 +85,39 @@ func setCachedFontData(assets []*Asset) {
cache.Set(cache_.FONTLISTCACHE, string(data), cache_.ONEDAY) cache.Set(cache_.FONTLISTCACHE, string(data), cache_.ONEDAY)
} }
func CascadiaCode() (*Asset, error) { func CascadiaCode() ([]*Asset, error) {
assets, err := fetchFontAssets("microsoft/cascadia-code") assets, err := fetchFontAssets("microsoft/cascadia-code")
if err != nil || len(assets) != 1 { if err != nil || len(assets) != 1 {
return nil, errors.New("no assets found") return nil, errors.New("no assets found")
} }
// patch the name return []*Asset{
assets[0].Name = CascadiaCodeMS {
Name: fmt.Sprintf("%s - TTF", CascadiaCodeMS),
return assets[0], nil URL: assets[0].URL,
Folder: "ttf/",
},
{
Name: fmt.Sprintf("%s - TTF Static", CascadiaCodeMS),
URL: assets[0].URL,
Folder: "ttf/static/",
},
{
Name: fmt.Sprintf("%s - OTF Static", CascadiaCodeMS),
URL: assets[0].URL,
Folder: "otf/static/",
},
{
Name: fmt.Sprintf("%s - WOFF2", CascadiaCodeMS),
URL: assets[0].URL,
Folder: "woff2/static/",
},
{
Name: fmt.Sprintf("%s - WOFF2 Static", CascadiaCodeMS),
URL: assets[0].URL,
Folder: "woff2/static/",
},
}, nil
} }
func fetchFontAssets(repo string) ([]*Asset, error) { func fetchFontAssets(repo string) ([]*Asset, error) {

View file

@ -45,7 +45,7 @@ func InstallZIP(data []byte, m *main) ([]string, error) {
} }
fontFileName := path.Base(file.Name) fontFileName := path.Base(file.Name)
fontRelativeFileName := strings.TrimPrefix(file.Name, m.zipFolder) fontRelativeFileName := strings.TrimPrefix(file.Name, m.Folder)
// do not install fonts that are not in the specified installation folder // do not install fonts that are not in the specified installation folder
if fontFileName != fontRelativeFileName { if fontFileName != fontRelativeFileName {

View file

@ -36,7 +36,7 @@ import (
"unicode/utf8" "unicode/utf8"
"github.com/jandedobbeleer/oh-my-posh/src/cache" "github.com/jandedobbeleer/oh-my-posh/src/cache"
fontCLI "github.com/jandedobbeleer/oh-my-posh/src/font" font_ "github.com/jandedobbeleer/oh-my-posh/src/font"
"github.com/jandedobbeleer/oh-my-posh/src/regex" "github.com/jandedobbeleer/oh-my-posh/src/regex"
"github.com/jandedobbeleer/oh-my-posh/src/runtime" "github.com/jandedobbeleer/oh-my-posh/src/runtime"
"github.com/jandedobbeleer/oh-my-posh/src/terminal" "github.com/jandedobbeleer/oh-my-posh/src/terminal"
@ -229,7 +229,7 @@ func (ir *Renderer) loadFonts() error {
url := "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.2.1/Hack.zip" url := "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.2.1/Hack.zip"
var err error var err error
data, err = fontCLI.Download(url) data, err = font_.Download(url)
if err != nil { if err != nil {
return err return err
} }

View file

@ -47,12 +47,6 @@ This will present a list of Nerd Font libraries, from which you can select `Mes
oh-my-posh font install meslo oh-my-posh font install meslo
``` ```
If you have a font that has specific flavors of a font inside sub folders, you can specify the sub folder name:
```bash
oh-my-posh font install --zip-folder ttf/static "CascadiaCode (MS)"
```
</TabItem> </TabItem>
<TabItem value="homebrew"> <TabItem value="homebrew">