Canop / broot

A new way to see and navigate directory trees : https://dystroy.org/broot
MIT License
10.48k stars 228 forks source link

Support Nerdfont Icons #333

Closed basbebe closed 4 months ago

basbebe commented 3 years ago

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

Canop commented 3 years ago

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

basbebe commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

basbebe commented 3 years ago

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!

cho-m commented 3 years ago

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.:

asdf8dfafjk commented 3 years ago

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 commented 3 years ago

@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 https://github.com/alacritty/alacritty/issues/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 commented 3 years ago

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 commented 3 years ago

@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 commented 3 years ago

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

AndydeCleyre commented 3 years ago

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 ~/.local/share/fonts /usr/share/fonts false false hintnone lcddefault rgb monospace Iosevka Term Custom Symbols Nerd Font JoyPixels Untitled1 serif Quando Symbols Nerd Font JoyPixels Untitled1 sans-serif Convergence Symbols Nerd Font JoyPixels Untitled1 emoji Symbols Nerd Font JoyPixels Untitled1 ```

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 ```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 ```xml @require(roles, options) ~/.local/share/fonts /usr/share/fonts @for key, val in options.items(): @(otype = 'bool' if val in ('true', 'false') else 'const')\ <@otype>@val @end @for role, prefs in roles.items(): @role @{prefs[0]} @for pref in prefs[1:]: @pref @end @end ```

And this (Zsh) command:

$ wheezy.template fonts.conf.wz =(yaml-get -p . vars.yml) >fonts.conf
cbirchinger commented 2 years ago

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 commented 1 year ago

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 commented 1 year ago

I use a modified version or urxvt with 3 fonts:

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 commented 1 year ago

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 commented 1 year ago

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

tkapias commented 1 year ago

@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 commented 1 year ago

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

asdf8dfafjk commented 1 year ago

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 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 commented 1 year ago

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 commented 1 year ago

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 commented 10 months ago

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 commented 6 months ago

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 commented 6 months ago

@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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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: and .

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 commented 6 months ago

@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!

texastoland commented 4 months ago

Can be closed 🚀