greshake / i3status-rust

Very resourcefriendly and feature-rich replacement for i3status, written in pure Rust
GNU General Public License v3.0
2.88k stars 475 forks source link

Add ability to define global pango markup wrappings #981

Open kneitinger opened 3 years ago

kneitinger commented 3 years ago

Hello all, great project! I'm in the process of porting my status from i3pystatus and having a wonderful time, but hit a small formatting roadblock that I wanted to get input on.

Problem Statement

I use an italic monospace font for i3, and due to that am having some issues with icon rendering in i3status-rs. All of my Font Awesome glyphs (both 4 and 5) are being italicized since my i3 bar config contains

2020-12-15_14-29-48

font pango:OperatorMonoMedium Italic 10

As far as I can tell, while i3 does support fallback fonts, it does not have the ability to specify individual styles or sizes for them versus the intended font.

It appears as though I could possibly use fontconfig to tell the renderer to never apply italics to Font Awesome 5 Free, but that is very cumbersome and I cannot imagine I'm the only one experiencing this issue.

One way around this would be to use pango markup to in my TOML, such as:

[icons.overrides]
bat_charging = "<span style=\"normal\">\uICON</span>"

if I want to keep my font the same, or

[[block]]
block = "net"
device = "wlp3s0"
interval = 5
format = "<span style=\"italic\">{ssid}[{ip}]</span>"
on_click = "nm-connection-editor"

as well as my i3 workspace labels, if I switch my font to normal and italicize everything I want.

In either of these options, there is a ton of manual override, which isn't a pleasant user experience.

Proposed Solution

I was thinking that instead of having to manually adjust every icon, or every format string, there could be a top-level TOML setting that specifies the format that is applied to all icons and/or all text, such as:

theme = "native"
icons = "awesome5"
icon_fmt = "<span style=\"normal\">{}</span>"
text_fmt = "<b>{}</b>"

[[block]]
...

where every icon or text string substitutes the {} in their respective formats.

With something like this, I can largely rely on the wonderful defaults of the themes and blocks, but apply my own styling to a type of element, as opposed individual icons or block texts.

What are your thoughts? If this sounds like a good idea to folks, I'm happy to implement it...I just wanted to make sure that I'm not missing a super obvious solution, and that this is something people would want!

ammgws commented 3 years ago

Sorry if I missed it but does this not also occur with i3pystatus? (Assuming it's the same as i3status-rust in that it outputs JSON for i3bar to parse and render)

kneitinger commented 3 years ago

Great question. I just restored my i3pystatus setup, and the behavior also happens there. 2020-12-15_16-22-42

However, there is a bit of difference in philosophy between i3pystatus (at least the last time I edited this a couple years ago :slightly_smiling_face:) and i3status-rs, particularly around theming and icons. i3pystatus doesn't have the notion of themes, and instead uses the i3 config defined colors. As for icons, I've just manually inserted Font Awesome glyphs into various modules' blocks:

    stat.register(
        "battery",
        interval=11,
        battery_ident="BAT0",
        critical_color="#ff0000",
        format="{status} {percentage:02.0f}% {remaining:%E%h:%M}",
        alert=False,
        alert_percentage=10,
        status={"DIS": u"()", "CHR": u"()", "FULL": u"(-)"},
    )

(which shows up/down-arrow + half full battery icon if charging/discharging, and a full battery icon if fully charged).

i3pystatus also speaks the same JSON format to i3bar, and I could insert the <span style=... markup into the above block to achieve the result on my icons. In i3pystatus, it would be easy to do this inline with the few icons I manually inserted, but in i3status-rs, there are a lot more to define, and I would need to look through the source code for the unicode chars to italicize all of the icon.overrides items' format while keeping their character.


I feel like with i3status-rs having a nicer explicit focus on appearance and style, it could be nice to have this feature, even if other's don't explicitly support it.

ammgws commented 3 years ago

That's fine, I just wanted to know if they were somehow doing something different. icon_fmt looks ok but text_fmt may be non-trivial to implement if actual pango markup escaping is required (search the issue tracker for past issues wrt escaping).

kneitinger commented 3 years ago

:+1: Thanks for your input! I agree about text_fmt, If I end up giving text_fmt a shot, I'll put it in a separate prototype PR with plenty of tests, but for now just focus on icons.

ammgws commented 3 years ago

Just a heads up, IIRC the only widget type that has pango support at the moment is the ButtonWidget, so you will have to add "markup": "pango" to the other widget types as well. And when you do that it is possible some pango escaping issues may pop up since it will apply to the text portion of the widget as well.

GladOSkar commented 3 years ago

This might be quite difficult as not all icons are embedded in the same way and there might be variances between blocks.

The easiest way to do it might be overriding the config.icons.get() method of the icon maps if that is possible or otherwise creating a new getter there that might apply the formatting.

kneitinger commented 3 years ago

Thanks for that pointer @GladOSkar. This is my first time working on this repo, and I spent yesterday evening just reading around the source. My initial proto-prototype deals with calling iter::map() on the icon Map, which worked decent in the one super basic case I tested my config with, but I don't expect this to just work for everything.

I would love spend a little bit more time reading over how all of the blocks and widgets operate to see if there is a refactor that puts this logic in a very clean place, as well as addresses the "markup":"pango" point @ammgws brought up.

I'll report back with my findings.

kneitinger commented 3 years ago

Got a very early prototype working! 2020-12-22_00-21-45

Format string used:

"<span style=\"normal\">  {}\u{200a}\u{200a}</span>"

The basic idea seems to work very nicely, and as expected, there is much work to be done with regard to pango-izing all of the blocks :slightly_smiling_face:

@kepi I played around with some of the unicode whitespace characters as well while I was at it. The \u{200a} after the {} (which represents the area to be replaced with the icon) is a thin unicode "hair space". i3bar rendered the various whitespace characters very well, and combinations of the different characters added a ton of spacing flexibility.

ammgws commented 3 years ago

@kneitinger #1095 should cover the icon part of your request, would you like to try it out?

ammgws commented 3 years ago

@kneitinger Friendly nudge

kneitinger commented 3 years ago

Hi thanks for the nudge, started using GitHub at work and my notifications exploded beyond usefulness :slightly_smiling_face:

Picking up work on this again, happy to try out the icons and build on that great work!