Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Nerdfont Icons #333

Closed
basbebe opened this issue Jan 31, 2021 · 31 comments
Closed

Support Nerdfont Icons #333

basbebe opened this issue Jan 31, 2021 · 31 comments

Comments

@basbebe
Copy link
Contributor

basbebe commented Jan 31, 2021

I think it would make sense to support Nerd Fonts icons since many other CLI tools use them already.

@Canop
Copy link
Owner

Canop commented Jan 31, 2021

This might be a dumb question but what's exactly the goal ?

@basbebe
Copy link
Contributor Author

basbebe commented Jan 31, 2021

This is not dumb at all, I think I didn't elaborate enough.

This would make icons work for many people (which use a Nerd Font in ther terminal anyway) 'out of the box', thereby removing the dependency of / the extra step needed to copy the vscode font.

@asdf8dfafjk
Copy link
Contributor

asdf8dfafjk commented Feb 10, 2021

Nerd font is woefully deficient when it comes to file icons...

Besides the copy step, there is no other work required.
We made it a point to ensure that none of the existing "popular" fonts points' clash with the font we created.

@basbebe
Copy link
Contributor Author

basbebe commented Feb 10, 2021

it's probably mostly about the copying, maybe my approach is not the best.

Projects like nnn and exa seem to include the icons with the build.

@asdf8dfafjk
Copy link
Contributor

asdf8dfafjk commented Feb 10, 2021

wget 'https://github.com/Canop/broot/blob/master/resources/icons/vscode/vscode.ttf?raw=true' -O broot_vscode.ttf

@basbebe
Copy link
Contributor Author

basbebe commented Feb 10, 2021

yes, I know. It's not htat hard to do, I'm just whining around 😅

no seriously: I thought that maybe that could be even more easier and low-barrier but the deficiency when it comes to files icons is a good point.

Adding them during the build might be a nice thing but of course it's not necessary!

@basbebe basbebe closed this as completed Feb 10, 2021
@cho-m
Copy link

cho-m commented Mar 9, 2021

I think it is worth keeping this feature request issue open for adding an icon_theme = "nerdfont", which would only support a limited subset of file types.

First, the current icon setup on macOS requires some additional steps due to some overlap in Apple's San Francisco font, e.g.
fontbook

Also, the vscode font also ends up installing as "Untitled1" font. Getting it to work on Kitty ends up requiring a Kitty symbol map config like:

symbol_map U+100000-U+100363 Untitled1

There may be some other ways to manipulate macOS's per-app font priorities that I am not aware of.
I haven't found if this is possible on iTerm2 and other terminals yet.


Another advantage would be to have a general consistency of icons aesthetic (in some cases, it may not be the same icon since each tool reimplements mapping) across the terminal. The relates to how many tools usually have some support for nerd-fonts, e.g.:

  • ls-alternative: lsd - default behavior
  • ls-alternative: exa - built-in and usable with --icons
  • file-manager: nnn - compile-time option
  • file-manager: hunter - same code from lsd is used
  • shell-prompt: starship - emojis are default, but documentation has runtime config for nerd-fonts
  • shell-prompt: powerlevel10k - one of the available settings to configure
  • multiple vim plugins via vim-devicons, e.g. NerdTree, lightline, ...

@Canop Canop reopened this Mar 9, 2021
@asdf8dfafjk
Copy link
Contributor

I haven't read the entire thing, and I am not familiar with how font priorities work on machinetosh but for me on Linux kitty works just fine without any mapping required.

It looks to me that SFCompact is using private space fonts on machinetosh-OS and that's obviously going to be problematic, no matter which font you use.

How do you know nerdfont doesn't (and won't tomorrow) clash with machinetosh's use of private space?

@cho-m
Copy link

cho-m commented Mar 9, 2021

@asdf8dfafjk
In some terminal emulators, the patched nerd fonts would be used since they don't support configuring fallback fonts. Since this is the main font set in the terminal, it should take precedence.

e.g. from iTerm2

Unpatched Monaco Patched JetBrains
unpatched patched

Notes on terminals below.

iTerm2

There is no support for multiple font selection (https://gitlab.com/gnachman/iterm2/-/issues/9073), which would mean the user may have to do one of:

Default macOS Terminal.app

I think this has same limitations of iTerm2

Kitty

Using symbol_map is usually the recommended method of enabling Powerline/NerdFonts and any other "special" fonts. So, it is probably a good idea to add broot icons as part of kitty config to guarantee fallback fonts.

The only problem right now is the missing font metadata, resulting in the font being called "Untitled1":
vscode
I think ttf should be updated with proper metadata for Font Family / Postscript Name / Full Name, so that the terminal configs look more reasonable.

Hyper

It looks like it supports fallback fonts via fontFamily, so should be similar to Kitty. This would mean adding "Untitled1" after main font but before any font that uses U+100000... range.

Alacritty

I don't know Alacritty's status on font configuration right now. Based on quick skim through alacritty/alacritty#957, it looks like there is mainly support for system font order for macOS (fontConfig on Linux), which ends up back to same issues as iTerm2.


EDIT: Additional terminal details, linking external issues, limitations

@asdf8dfafjk
Copy link
Contributor

That's very well written text I must say. I haven't read much of it since I don't have a machinetosh machine but I can help you by telling you the steps required to support NerdFonts

There are two main directories involved:

https://github.com/Canop/broot/tree/master/src/icon and https://github.com/Canop/broot/tree/master/resources

In the former (code), edit mod.rs, and copy-paste vscode.rs to nerdfont.rs and replace vscode with nerdfont (This is the lazy way for quick local changes).

In the latter (resources)

Start by making icons/nerdfont. The process would be cloning git broot locally and then making changes one by one (if you make it one go it'd be tiring). You'll also need to recompile .

Copy these 4 files https://github.com/Canop/broot/tree/master/resources/icons/vscode/data

You should get a sense of the files easily but to help you, the last file there maps a "<icon name (that you would generate as you please with no connection to anything)>" to a unicode point in nerdfont. You obviously already seem facile enough with unicode stuff so that latter is going to be easy.

Then appropriately in the first 3 files map the entity to the icon name you just generated.

@cho-m
Copy link

cho-m commented Mar 11, 2021

@asdf8dfafjk Thanks for info. I'll see if I have some time to try creating a mapping.

I did try mapping a few, and do see it working in local build:
nerdfonts

EDIT: For anyone who sees this issue, current work - https://github.com/cho-m/broot/tree/nerdfont-icons/resources/icons/nerdfont

@asdf8dfafjk
Copy link
Contributor

I took a quick look, you're on the right track. (Just remove the duplication across vscode and nerdtree before PR).

@AndydeCleyre
Copy link

AndydeCleyre commented May 25, 2021

Besides the copy step, there is no other work required.

@asdf8dfafjk

This is false, at least on Arch Linux, using Plasma desktop.

I have no idea how the right characters are expected to be found, but AFAICT the "proper" thing to do is use fontconfig to set the new, woefully named "Untitled1" font, as a fallback for at least the mono category.

Example ~/.config/fontconfig/fonts.conf
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>

    <dir>~/.local/share/fonts</dir>
    <dir>/usr/share/fonts</dir>

    <match target="font">
        <edit mode="assign" name="autohint"><bool>false</bool></edit>
        <edit mode="assign" name="hinting"><bool>false</bool></edit>
        <edit mode="assign" name="hintstyle"><const>hintnone</const></edit>
        <edit mode="assign" name="lcdfilter"><const>lcddefault</const></edit>
        <edit mode="assign" name="rgba"><const>rgb</const></edit>
    </match>

    <match target="pattern">
        <test qual="any" name="family"><string>monospace</string></test>
        <edit name="family" mode="assign" binding="same"><string>Iosevka Term Custom</string></edit>
        <edit name="family" mode="append" binding="weak"><string>Symbols Nerd Font</string></edit>
        <edit name="family" mode="append" binding="weak"><string>JoyPixels</string></edit>
        <edit name="family" mode="append" binding="weak"><string>Untitled1</string></edit>
    </match>

    <match target="pattern">
        <test qual="any" name="family"><string>serif</string></test>
        <edit name="family" mode="assign" binding="same"><string>Quando</string></edit>
        <edit name="family" mode="append" binding="weak"><string>Symbols Nerd Font</string></edit>
        <edit name="family" mode="append" binding="weak"><string>JoyPixels</string></edit>
        <edit name="family" mode="append" binding="weak"><string>Untitled1</string></edit>
    </match>

    <match target="pattern">
        <test qual="any" name="family"><string>sans-serif</string></test>
        <edit name="family" mode="assign" binding="same"><string>Convergence</string></edit>
        <edit name="family" mode="append" binding="weak"><string>Symbols Nerd Font</string></edit>
        <edit name="family" mode="append" binding="weak"><string>JoyPixels</string></edit>
        <edit name="family" mode="append" binding="weak"><string>Untitled1</string></edit>
    </match>

    <match target="pattern">
        <test qual="any" name="family"><string>emoji</string></test>
        <edit name="family" mode="assign" binding="same"><string>Symbols Nerd Font</string></edit>
        <edit name="family" mode="append" binding="weak"><string>JoyPixels</string></edit>
        <edit name="family" mode="append" binding="weak"><string>Untitled1</string></edit>
    </match>

</fontconfig>

In my personal aversion to XML (especially because Plasma reformats this file to make it less legible to me), I generate that using yamlpath and wheezy.template from PyPI, with the following:

vars.yml
roles:
  monospace:
  - Iosevka Term Custom
  - Symbols Nerd Font
  - JoyPixels
  - Untitled1
  serif:
  - Quando
  - Symbols Nerd Font
  - JoyPixels
  - Untitled1
  sans-serif:
  # - Barlow Medium
  # - Baloo 2 Medium
  - Convergence
  - Symbols Nerd Font
  - JoyPixels
  - Untitled1
  emoji:
  - Symbols Nerd Font
  - JoyPixels
  - Untitled1
options:
  autohint: 'false'
  hinting: 'false'
  hintstyle: hintnone
  lcdfilter: lcddefault
  rgba: rgb
fonts.conf.wz
@require(roles, options)
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>

    <dir>~/.local/share/fonts</dir>
    <dir>/usr/share/fonts</dir>

    <match target="font">
        @for key, val in options.items():
        @(otype = 'bool' if val in ('true', 'false') else 'const')\
        <edit mode="assign" name="@key"><@otype>@val</@otype></edit>
        @end
    </match>
    @for role, prefs in roles.items():

    <match target="pattern">
        <test qual="any" name="family"><string>@role</string></test>
        <edit name="family" mode="assign" binding="same"><string>@{prefs[0]}</string></edit>
        @for pref in prefs[1:]:
        <edit name="family" mode="append" binding="weak"><string>@pref</string></edit>
        @end
    </match>
    @end

</fontconfig>

And this (Zsh) command:

$ wheezy.template fonts.conf.wz =(yaml-get -p . vars.yml) >fonts.conf

@cbirchinger
Copy link

I needed a fontconfig entry too to make it work in more terminals. Some (like Wezterm) still refuse to display those symbols, but that's not a broot issue.

Giving it a proper TTF name instead of Untitled1 makes it a bit nicer too:

~$ fontname.py "Broot VSCode" /path/to/broot_vscode.ttf

Tool is available here:
https://github.com/chrissimpkins/fontname.py

@asdf8dfafjk
Copy link
Contributor

On that note, I came across this https://old.reddit.com/r/i3wm/comments/y48a61/nerdfonts_cheatsheet_offline/ if someone is working on the nerdfont thing.

@cbirchinger Surprised that fc-cache (fontconfig cache updater) wasn't enough. In any case, the steps I mention are somewhat complete (to my knowledge) in the sense that any application using fontconfig should be able to fall back to vscode fonts . I do not know how wezterm and co make their font rendering decisions.

@tkapias
Copy link

tkapias commented Mar 13, 2023

I use a modified version or urxvt with 3 fonts:

  • A nerdified IBM Mono
  • Noto Color Emoji
  • Symbola with a modified width

To add a font for Urxvt the width needs to be adapted first, then fc-cache and addition to the conf. So it's not an easy process.

But thanks to a large usage of Nerdfont icons on other projects I have icons in exa, vifm and others out of the box now.

Broot seems nice so I will try to modify the vscode.ttf. But adding NerdFont would be nice.

@tkapias
Copy link

tkapias commented Mar 13, 2023

In my case vscode.ttf width is too irregular, and even after processing it with monospacifier some icons are still too width. I fixed other fonts like symbola with this technique.

Most fonts generated with --mono in NerdFont are correct.

@asdf8dfafjk
Copy link
Contributor

@tkapias Please consider reading the entire discussion, that would help I think.

@tkapias
Copy link

tkapias commented Mar 16, 2023

@asdf8dfafjk I should have read a little more the part about resources/icons/nerdfont, my main goal was to give another example of a terminal (urxvt) where the inclusion of a new font is not a good enough strategy.

I will do something else.
I will extract all the glyphs and codepoints to a new ttf and add it to the collection of glyphs usable in the generation of nerdfonts. This way anyone using Nerdfonts can just regen a compatible font without any modification to broot or the terminal config.

I will update the method/ressources here soon.

@asdf8dfafjk
Copy link
Contributor

Please do not hesitate to ask for help. Happy to guide you over chat as well.

@asdf8dfafjk
Copy link
Contributor

So I'm not an expert I have to admit but on linux, my understanding is that the final "rendering" is provided by font config, and if a GUI app uses font config then there shouldn't be any additional work. I mean I've only done fc-cache on my computer but fontconfig allows for easy fallbacks.

Here are some of my notes on fontconfig, please see if they help you.

Two systems fontconfig vs XSETTINGS. More here: http://neugierig.org/software/chromium/fonts/

fontconfig

http://www.linuxfromscratch.org/blfs/view/svn/x/tuning-fontconfig.html

/etc/fonts
conf.d has files pointing to conf.avail. The configuration as of this writing with 20-monaco-no-embedded.conf show Monaco reasonably well. Go through more revisions to find out. Also, the issue at small sizes is only at such sizes, so comparing at increased font sizes will not help.

For Monaco absolutely important:
name:autohint -> mode:append -> value:true

Pretty important:
name:hinstyle -> mode:append/assign -> value:hintnone

After adding fonts, or changing font config

fc-cache -fvr --really-force ~/.fonts
fc-cache -fvr --really-force ~/.local/share/fonts

Find font installed for languages

fc-list -f '%{file}\n' :lang=zh

Find font that contains a character

fc-match -s monospace:charset=1F4A9

Find font that matches a style 'sans', 'serif', 'cursive'

fc-match -s 'sans'

Find all points supported by a font

fc-query <filename.ttf>
fc-list FontNameNoSpaces –v

Take the 8 bits off the symbol you're looking for-
say 20B9 (rupee sign) so taking 8 bits
= 2 hex digits off, you get 20.
Look for a row with header 20.
See the coverage there.

Find fonts that supply a language

fc-list ":lang=zh-CN:scalable=true" family

Language difference

FC_DEBUG=4 pango-view --language=ja_JP --text 語
With japanese, the second quadrant should show up as 4 bars, with chinese as a lid and two bars.

XSETTINGS

Wherever you see Xft, that's XSETTINGS. Firefox is weird

DISPLAY FONT:

  1. fontpreview
  2. See ~/.cheat/images (Display font character)
  3. dp4 font viewer (with wine)
  4. fontaine (pip install)
  5. See fontforge.md for getting python repl
  6. Google- fonttools and nototools

@asdf8dfafjk
Copy link
Contributor

On that note, next time you encounter a character that's too wide, could you paste it here? I would likely do nothing right away but if I take a look at this again, I would see what I can do.

@JonasLeonhard
Copy link
Contributor

if someone starts working on implementing nerdfonts again. I created a updated icon_theme: "nerdfont" setting for the current master branch in: https://github.com/JonasLeonhard/broot with nerdfont translations for all icons i could find. Thanks cho-m for the inspiration! Someone should probably double check the icons though.

@limaceous-bushwhacker
Copy link

if someone starts working on implementing nerdfonts again. I created a updated icon_theme: "nerdfont" setting for the current master branch in: https://github.com/JonasLeonhard/broot with nerdfont translations for all icons i could find. Thanks cho-m for the inspiration! Someone should probably double check the icons though.

Thank you so much! It seems to work really well. Now I can get rid of those vscode icons.

@texastoland
Copy link
Contributor

texastoland commented Feb 5, 2024

The relates to how many tools usually have some support for nerd-fonts, e.g.:

I created a updated icon_theme: "nerdfont" setting for the current master branch in: JonasLeonhard/broot with nerdfont translations for all icons i could find.

@Canop Candidate for PR?

@Canop
Copy link
Owner

Canop commented Feb 5, 2024

@Canop Candidate for PR?

If you think it's good and doesn't introduce licensing problems, then a PR would probably be welcome.
As I lack time to try everything, I need the help of the community for the approval and verification of this feature.

@texastoland
Copy link
Contributor

If you think it's good and doesn't introduce licensing problems,

The patched fonts maintainer stays on top of licensing 👍🏼

a PR would probably be welcome.

@JonasLeonhard Still interested?

@JonasLeonhard
Copy link
Contributor

Heyho everyone,

I've been using the nerdfont version of my master branch ever since i made the comment in this thread.
Mostly because im using alacritty, which to my knowledge doesn't support the vscode font fallbacks (atleast i could't get it to work). Therefore i would love to help out!

In its current state, the nerdfont setting works good enough for my use cases. However, I believe it is not quite ready for production. Certain icon mappings, such as "folders, .json .gitignore, markdown, rust and others" function as expected. Conversely, icons like ".js, .vue, .go, .jsx" currently display a generic file icon and require proper mapping.

That beeing said, i will try to work on this when i find some time.

JonasLeonhard added a commit to JonasLeonhard/broot that referenced this issue Feb 10, 2024
This commit adds "icon_theme: nerdfont" as a setting to the broot conf.hjson file.

1. In order for the nerdfont setting to work you need to have a patched
font installed. See: https://github.com/ryanoasis/nerd-fonts

2. After a successful installation, you need to add "icon_theme:
nerdfont" to your broot conf.hjson file:

```hjson
icon_theme: "nerdfont"
```

3. Congratulations! You should now be able to see icons when opening broot
in your terminal.

This commit adds a new NerdfontIconPlugin to icon/mod.rs. The structure
of the plugin is based on the existing vscode icon plugin.
It maps incoming filenames based on mappings inside of
icons/nerdfont/data/*_map.rs files.

The iconset is limited by available nerdfont icons. Some icons simply
don't exist as of yet. Eg. a vite or prettier icon.

Thank you for putting me into the right direction:
- Canop#333 (comment)
- Canop#333 (comment)
@JonasLeonhard
Copy link
Contributor

Good news everyone.

The first version of the "icon_theme: nerdfont" settings is now available for testing. I added a "icon_theme: nerdfont" setting to the broot conf.hjson file.

I would love for someone to test this branch before i create a pull request!

Installation

Branch:
https://github.com/JonasLeonhard/broot/tree/feature/nerdfont

  1. In order for the nerdfont setting to work you need to have a patched
    font installed. See: https://github.com/ryanoasis/nerd-fonts

  2. After a successful installation, you need to add "icon_theme:
    nerdfont" to your broot conf.hjson file:

icon_theme: "nerdfont"
  1. Congratulations! You should now be able to see icons when opening broot
    in your terminal.

How it works:

This commit adds a new NerdfontIconPlugin to icon/mod.rs. The structure
of the plugin is based on the existing vscode icon plugin.
It maps incoming filenames based on mappings inside of
icons/nerdfont/data/*_map.rs files.

Limitations:

The iconset is limited by available nerdfont icons. Some icons simply
don't exist as of yet. Eg. a vite or prettier icon. You can find available icons here: https://www.nerdfonts.com/cheat-sheet.

How to do i test this?

  1. Follow the installation instructions above
  2. Browse different filetypes.

I found a file that is not mapped or wrongly mapped!

Lets say you find some file icon you think i forgot or mapped wrong. Please go to https://www.nerdfonts.com/cheat-sheet and search for an icon you would like to set in its place.

In order to correctly fix the icon mapping i need: <FILE_EXTENSION> and <NERDFONT_ICON_CODE>.

Lets say you think the .json icon is incorrect.

  1. Search for json in the cheatsheet
  2. Copy the nerdfont iconCode ("the code inside the red box in the screenshot below")
    iconCode
  3. Tell me that .json files need the icon eb0f

Credits:

Thank you for putting me into the right direction:

Screenshots

broot_nerdfonts

@texastoland
Copy link
Contributor

texastoland commented Feb 10, 2024

@JonasLeonhard Can you open a PR for line by line feedback? I looked over your changes previously but that'd be preferable for review and refining scope. Feel free to enable draft mode if you consider it WIP!

JonasLeonhard added a commit to JonasLeonhard/broot that referenced this issue Feb 23, 2024
accepting paths (Canop#333, Canop#833)

this applies the refactor suggestion by texastoland: Canop#833 (comment)

This commit

- renames the existing VsCodeIconPlugin into FontPlugin. The only
  change made to the plugin is in the new() function. It now accepts a
  reference to an !included static array of touples as found in the
  icon_name_to_icon_codepoint_map, double_extension_to_icon_name_map,
  extension_to_icon_name_map and file_name_to_icon_name_map.

  This should be easier to maintain than two seperate plugin files.
JonasLeonhard added a commit to JonasLeonhard/broot that referenced this issue Feb 25, 2024
@texastoland
Copy link
Contributor

Can be closed 🚀

@Canop Canop closed this as completed Apr 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants