mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-01-11 11:17:27 -08:00
feat(font): allow installing from a specific zip file folder
Some checks are pending
Code QL / code-ql (push) Waiting to run
Azure Static Web Apps CI/CD / Build and Deploy (push) Waiting to run
Release / changelog (push) Waiting to run
Release / artifacts (push) Blocked by required conditions
Release / msi (arm64) (push) Blocked by required conditions
Release / msi (x64) (push) Blocked by required conditions
Release / msi (x86) (push) Blocked by required conditions
Release / release (push) Blocked by required conditions
Some checks are pending
Code QL / code-ql (push) Waiting to run
Azure Static Web Apps CI/CD / Build and Deploy (push) Waiting to run
Release / changelog (push) Waiting to run
Release / artifacts (push) Blocked by required conditions
Release / msi (arm64) (push) Blocked by required conditions
Release / msi (x64) (push) Blocked by required conditions
Release / msi (x86) (push) Blocked by required conditions
Release / release (push) Blocked by required conditions
This commit is contained in:
parent
b4b2fd02d5
commit
a7ad857a2d
|
@ -11,7 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ttf bool
|
zipFolder string
|
||||||
|
|
||||||
fontCmd = &cobra.Command{
|
fontCmd = &cobra.Command{
|
||||||
Use: "font [install|configure]",
|
Use: "font [install|configure]",
|
||||||
|
@ -47,7 +47,7 @@ This command is used to install fonts and configure the font in your terminal.
|
||||||
|
|
||||||
terminal.Init(env.Shell())
|
terminal.Init(env.Shell())
|
||||||
|
|
||||||
font.Run(fontName, env.Cache(), env.Root(), ttf)
|
font.Run(fontName, env.Cache(), env.Root(), zipFolder)
|
||||||
|
|
||||||
return
|
return
|
||||||
case "configure":
|
case "configure":
|
||||||
|
@ -60,6 +60,6 @@ This command is used to install fonts and configure the font in your terminal.
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
fontCmd.Flags().BoolVar(&ttf, "ttf", false, "fetch the TTF version of the font")
|
fontCmd.Flags().StringVar(&zipFolder, "zip-folder", "", "the folder inside the zip file to install fonts from")
|
||||||
RootCmd.AddCommand(fontCmd)
|
RootCmd.AddCommand(fontCmd)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,14 +72,14 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type main struct {
|
type main struct {
|
||||||
err error
|
err error
|
||||||
list *list.Model
|
list *list.Model
|
||||||
font string
|
font string
|
||||||
families []string
|
zipFolder string
|
||||||
spinner spinner.Model
|
families []string
|
||||||
state state
|
spinner spinner.Model
|
||||||
system bool
|
state state
|
||||||
ttf bool
|
system bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *main) buildFontList(nerdFonts []*Asset) {
|
func (m *main) buildFontList(nerdFonts []*Asset) {
|
||||||
|
@ -121,18 +121,18 @@ func downloadFontZip(location string) {
|
||||||
program.Send(zipMsg(zipFile))
|
program.Send(zipMsg(zipFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
func installLocalFontZIP(zipFile string, user, ttf bool) {
|
func installLocalFontZIP(m *main) {
|
||||||
data, err := os.ReadFile(zipFile)
|
data, err := os.ReadFile(m.font)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
program.Send(errMsg(err))
|
program.Send(errMsg(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
installFontZIP(data, user, ttf)
|
installFontZIP(data, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func installFontZIP(zipFile []byte, user, ttf bool) {
|
func installFontZIP(zipFile []byte, m *main) {
|
||||||
families, err := InstallZIP(zipFile, user, ttf)
|
families, err := InstallZIP(zipFile, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
program.Send(errMsg(err))
|
program.Send(errMsg(err))
|
||||||
return
|
return
|
||||||
|
@ -148,21 +148,30 @@ func (m *main) Init() tea.Cmd {
|
||||||
|
|
||||||
if len(m.font) != 0 && !isLocalZipFile() {
|
if len(m.font) != 0 && !isLocalZipFile() {
|
||||||
m.state = downloadFont
|
m.state = downloadFont
|
||||||
|
|
||||||
if !strings.HasPrefix(m.font, "https") {
|
if !strings.HasPrefix(m.font, "https") {
|
||||||
m.font = fmt.Sprintf("https://github.com/ryanoasis/nerd-fonts/releases/latest/download/%s.zip", m.font)
|
if strings.HasPrefix(m.font, "CascadiaCode-") {
|
||||||
|
version := strings.TrimPrefix(m.font, "CascadiaCode-")
|
||||||
|
m.font = fmt.Sprintf("https://github.com/microsoft/cascadia-code/releases/download/v%s/%s.zip", version, m.font)
|
||||||
|
} 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.font)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
m.spinner.Spinner = spinner.Globe
|
m.spinner.Spinner = spinner.Globe
|
||||||
return m.spinner.Tick
|
return m.spinner.Tick
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if isLocalZipFile() {
|
if isLocalZipFile() {
|
||||||
go installLocalFontZIP(m.font, m.system, m.ttf)
|
go installLocalFontZIP(m)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go getFontsList()
|
go getFontsList()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -171,6 +180,7 @@ func (m *main) Init() tea.Cmd {
|
||||||
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("170"))
|
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("170"))
|
||||||
m.spinner = s
|
m.spinner = s
|
||||||
m.state = getFonts
|
m.state = getFonts
|
||||||
|
|
||||||
if isLocalZipFile() {
|
if isLocalZipFile() {
|
||||||
m.state = unzipFont
|
m.state = unzipFont
|
||||||
}
|
}
|
||||||
|
@ -240,7 +250,7 @@ func (m *main) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
case zipMsg:
|
case zipMsg:
|
||||||
m.state = installFont
|
m.state = installFont
|
||||||
defer func() {
|
defer func() {
|
||||||
go installFontZIP(msg, m.system, m.ttf)
|
go installFontZIP(msg, m)
|
||||||
}()
|
}()
|
||||||
m.spinner.Spinner = spinner.Dot
|
m.spinner.Spinner = spinner.Dot
|
||||||
return m, m.spinner.Tick
|
return m, m.spinner.Tick
|
||||||
|
@ -288,6 +298,10 @@ func (m *main) View() string {
|
||||||
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:
|
||||||
|
if len(m.families) == 0 {
|
||||||
|
return textStyle.Render(fmt.Sprintf("No matching font families were installed. Try setting --zip-folder to the correct folder when using Cascadia Code or a custom font zip file %s", terminal.StopProgress())) //nolint: lll
|
||||||
|
}
|
||||||
|
|
||||||
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()))
|
||||||
|
@ -307,11 +321,11 @@ func (m *main) View() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(font string, ch cache_.Cache, root, ttf bool) {
|
func Run(font string, ch cache_.Cache, root bool, zipFolder string) {
|
||||||
main := &main{
|
main := &main{
|
||||||
font: font,
|
font: font,
|
||||||
system: root,
|
system: root,
|
||||||
ttf: ttf,
|
zipFolder: zipFolder,
|
||||||
}
|
}
|
||||||
|
|
||||||
cache = ch
|
cache = ch
|
||||||
|
|
|
@ -25,13 +25,7 @@ func contains[S ~[]E, E comparable](s S, e E) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func InstallZIP(data []byte, user, ttf bool) ([]string, error) {
|
func InstallZIP(data []byte, m *main) ([]string, error) {
|
||||||
// prefer OTF over TTF; otherwise prefer the first font we find
|
|
||||||
extension := ".otf"
|
|
||||||
if ttf {
|
|
||||||
extension = ".ttf"
|
|
||||||
}
|
|
||||||
|
|
||||||
var families []string
|
var families []string
|
||||||
bytesReader := bytes.NewReader(data)
|
bytesReader := bytes.NewReader(data)
|
||||||
|
|
||||||
|
@ -42,46 +36,56 @@ func InstallZIP(data []byte, user, ttf bool) ([]string, error) {
|
||||||
|
|
||||||
fonts := make(map[string]*Font)
|
fonts := make(map[string]*Font)
|
||||||
|
|
||||||
for _, zf := range zipReader.File {
|
root := len(m.zipFolder) == 0
|
||||||
|
|
||||||
|
for _, file := range zipReader.File {
|
||||||
// prevent zipslip attacks
|
// prevent zipslip attacks
|
||||||
// https://security.snyk.io/research/zip-slip-vulnerability
|
// https://security.snyk.io/research/zip-slip-vulnerability
|
||||||
if strings.Contains(zf.Name, "..") {
|
// and only process files which are in the specified folder
|
||||||
|
if strings.Contains(file.Name, "..") || !strings.HasPrefix(file.Name, m.zipFolder) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := zf.Open()
|
fontFileName := path.Base(file.Name)
|
||||||
if err != nil {
|
|
||||||
return families, err
|
// do not install fonts that are not in the root folder when specified as such
|
||||||
|
if root && fontFileName != file.Name {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
defer rc.Close()
|
fontReader, err := file.Open()
|
||||||
|
|
||||||
data, err := io.ReadAll(rc)
|
|
||||||
if err != nil {
|
|
||||||
return families, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fontData, err := newFont(path.Base(zf.Name), data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, found := fonts[fontData.Name]; !found {
|
defer fontReader.Close()
|
||||||
fonts[fontData.Name] = fontData
|
|
||||||
|
fontBytes, err := io.ReadAll(fontReader)
|
||||||
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// respect the user's preference for TTF or OTF
|
font, err := newFont(fontFileName, fontBytes)
|
||||||
first := strings.ToLower(path.Ext(fonts[fontData.Name].FileName))
|
if err != nil {
|
||||||
second := strings.ToLower(path.Ext(fontData.FileName))
|
continue
|
||||||
if first != second && second == extension {
|
}
|
||||||
fonts[fontData.Name] = fontData
|
|
||||||
|
if _, found := fonts[font.Name]; !found {
|
||||||
|
fonts[font.Name] = font
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// prefer .ttf files over other file types when we have a duplicate
|
||||||
|
first := strings.ToLower(path.Ext(fonts[font.Name].FileName))
|
||||||
|
second := strings.ToLower(path.Ext(font.FileName))
|
||||||
|
if first != second && second == ".ttf" {
|
||||||
|
fonts[font.Name] = font
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, font := range fonts {
|
for _, font := range fonts {
|
||||||
if err = install(font, user); err != nil {
|
if err = install(font, m.system); err != nil {
|
||||||
return families, err
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if found := contains(families, font.Family); !found {
|
if found := contains(families, font.Family); !found {
|
||||||
|
|
|
@ -34,6 +34,7 @@ Oh My Posh has a CLI to help you select and install a [Nerd Font][nerdfonts]:
|
||||||
:::info
|
:::info
|
||||||
When running as root/administrator, the fonts will be installed system-wide.
|
When running as root/administrator, the fonts will be installed system-wide.
|
||||||
When running as a regular user, the fonts will be installed in the user's font directory.
|
When running as a regular user, the fonts will be installed in the user's font directory.
|
||||||
|
By default, Oh My Posh installs the `.ttf` version of the font in case multiple versions are available.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -46,10 +47,10 @@ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, Oh My Posh installs the `.otf` version of the font. If you prefer the `.ttf` version, you can specify it with the `--ttf` flag:
|
If you have a font that has specific flavors of a font inside sub folders, you can specify the sub folder name:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
oh-my-posh font install meslo --ttf
|
oh-my-posh font install --zip-folder ttf/static CascadiaCode-2407.24
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
Loading…
Reference in a new issue