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

Formatter new features #752

Closed
tobes opened this issue Feb 15, 2017 · 38 comments
Closed

Formatter new features #752

tobes opened this issue Feb 15, 2017 · 38 comments
Labels
feature request 🙏 I am requesting a feature

Comments

@tobes
Copy link
Contributor

tobes commented Feb 15, 2017

I'm planning to add some new formatter features.

Current features for blocks.

  • colors [\?color=bad ...]

  • conditions [\?if=condition ...] including negation [\?if=!condition ...]

  • always show block [\?show ...]

  • options, choose first with output [...|...|...]

  • text size [\?min_size=7 ...], [\?max_size=17 ...]

  • do not count 0 as valid eg no notifications [\?not_zero ...]

The new options I'm thinking of adding are below, please vote on any you would like to see or are opposed to. I'll make each as a new reply.

Also feel free to add suggestions

@tobes
Copy link
Contributor Author

tobes commented Feb 15, 2017

ellipsis for shortened strings

\?max_length=12&ellipsis=…

@tobes
Copy link
Contributor Author

tobes commented Feb 15, 2017

symmetric shortening etc. allow trimming left, right, both

\?max_length=12&trim=both

@tobes
Copy link
Contributor Author

tobes commented Feb 15, 2017

soft spaces.

Often we want a separator but only if needed eg {artist} - {title} but maybe we have just one or both

{artist}[\?soft - ]{title} it would only show if it has non-whitespace before and after.

@lasers
Copy link
Contributor

lasers commented Feb 15, 2017

and condition: \?if pacman&aur=... (I vote +1 on this ; but might be easier for users if we fix arch_updates to have three possible results instead.)

Could be good to have &trim=both strip_whitespace as default for all modules so we don't waste time giving users left,right,both option or adding .strip ourselves (in some modules) to trim some unwanted spaces on certain modules when there is no input and/or delayed input... such as clementine, bluetooth, and xsel.

|BT: | (default 'BT: {format_bt}')     <-- Space
|♫ | (default '♫ {current}')           <-- Space
|       ayayaya xsel content lmao    | <-- Spaces

────────── DIVIDER ──────────

always show block [\?show ...] is somewhat vague. I think \?always_show is better.
Nitpicking?

────────── DIVIDER ──────────

Soft spaces could be perfect for colons too.
BT[\?soft : ]{bluetooth} Sometimes none due to delayed/slow/off response.

There should be some other modules just like that too. No song playing, etc.

────────── DIVIDER ──────────

Unrelated: An ability to override STRING_ERROR / STRING_UNAVAILABLE.

@tobes
Copy link
Contributor Author

tobes commented Feb 16, 2017

BT[\?soft : ]{bluetooth} actually BT[: {bluetooth}] probably works just as well

@lasers
Copy link
Contributor

lasers commented Feb 20, 2017

I think I need to wait for new formatters before I make uptime PR.

Something to make hours|hour possible.

    # available configuration parameters
    format = 'up {decades}{years}{weeks}{days}{hours}{minutes}'
    decades = '[\?if=D {D} decades, ]'
    years = '[\?if=Y {Y} years, ]'
    weeks = '[\?if=w {w} weeks, ]'
    days = '[\?if=d {d} days, ]'
    hours = '[\?if=h {h} hours, ]'
    minutes = '[\?if=m {m} minutes, ]'
    seconds = '[\?if=s {s} seconds, ]'

[\?soft ,] would be nice for comma. I have .rstrip(' ').rstrip(',') before it goes out.

@tobes
Copy link
Contributor Author

tobes commented Feb 20, 2017

Something to make hours|hour possible.

it might be possible to do something like {hour} [\?plural=hours hour|hours] but this feels a bit messy. The reason I'd do it like this would be to allow it to be used across multiple languages see https://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/Plural-forms.html. So to do it properly we would have to learn about language plurals.

We could just do it for English and most other European languages (interestingly not French) but I'd prefer a full implementation.

A problem is that it might be over complicated for users, also getting the plural types for all different languages would be a pain (I can't seem to find them easily)

@lasers
Copy link
Contributor

lasers commented Feb 20, 2017

What about just not_one similar to not_zero?

[?\not_one {h} hours|hour]

@tobes
Copy link
Contributor Author

tobes commented Feb 20, 2017

What about just not_one

I care about the french 🇫🇷

@lasers
Copy link
Contributor

lasers commented Mar 19, 2017

# keyboard_locks
format = '{caps} {num} {scr}'
icon_scr_off= ""
icon_num_off = ""
icon_caps_off = ""

... does not work as expected due to spaces. Soft spaces may be perfect for this.

# New format
format = '[{caps}][\?soft  ][{num}][\?soft  ][{scr}]'

Maybe we could make[\?space] or just keep using [\?soft ] (Two spaces).

# New format
format = '[{caps}][\?space][{num}][\?space][{scr}]'

EDIT: Maybe make it smart like this if no character(s) detected.

# New format
format = '[{caps}][\?soft][{num}][\?soft][{scr}]'

@tobes
Copy link
Contributor Author

tobes commented Mar 19, 2017

how about format = '{caps}[\?soft]{num}[\?soft]{scr}'?

I like the [\?soft] will be a space by default idea.

It is a shame that '{caps} {num} {scr}' doesn't just do this by default (eating whitespace) I might see how that works out. Not sure how many modules it'd break

@lasers
Copy link
Contributor

lasers commented Mar 19, 2017

Two modules off my head... xsel and clementine.

For clementine, format = u'♫ {current}'. If empty, would be '♫ ' (no quote).
Maybe we change default format for clementine? Make it format = u'♫[ {current}'] ?
That was pretty annoying.

We could do same for any other similar module (if we find them).

@lasers
Copy link
Contributor

lasers commented Mar 19, 2017

Something inverse of [?\soft]......... [?\omit ,] or [\strip ,]?

format = 'up [\?if=W {W} weeks, ][\?if=D {D} days, ][\?if=H {H} hours, ][\?if=M {M} minutes, ][?\omit ,]'

Can be crazy if we toss in [?\soft ,] for all those things.
Keep modules clean. Then we can remove uptime = uptime.rstrip(' ').rstrip(',').

EDIT: Smart suggestion.

[\?strip] removes whitespace.
[\?strip=,] removes whitespace+comma+whitespace.
[\?strip=,:] removes whitespace+comma+colon+whitespace.

I suppose we could be cleaner by not assuming we want to strip whitespace in second, third lines, but I can't think of scenario where we want to keep whitespace at end for the modules since I assume we will be mostly using [\?strip] something always at end of the format.

@lasers
Copy link
Contributor

lasers commented Mar 29, 2017

Place an extra 0 in front of single digit numbers. 5 becomes 05... foruptime.

@tobes
Copy link
Contributor Author

tobes commented Mar 30, 2017

Place an extra 0 in front of single digit numbers. 5 becomes 05... for uptime.

{minutes:02d} sounds like what you want

@lasers
Copy link
Contributor

lasers commented Mar 30, 2017

I think we ought to have something like this [\?color=color {status}] to pass color so we don't paint format with unwanted color_good, color_bad, or color_degraded. We might have to update format for all modules with this if we want full color customization. See example.

Current
format = 'Dropbox: {status}' --> (color) Dropbox: {status}
// Always red, green or yellow.

New format... Same as Current
format = '[\?color=color Dropbox: {status}]' --> (color) Dropbox: {status}
// Always red, green, or yellow

Customizing...
format = 'Dropbox: [\?color=color {status}]' --> (white) Dropbox: (color) {status}.
// Always white // Always red, green, or yellow

Note: (white) is not necessarily white, but the statusline color in our i3 config.

 *Example (default colors)*:
 --------------------------------------
 bar {
     colors {
         background #000000
         statusline #ffffff    <---------- This.
         separator #666666
     }
 }

This way, I think, would allow us to change statusline color for all modules and would make it possible for people to keep all modules consistent with just 6 existing color options after they finished setting up new format for all modules.

EDIT: Maybe just [\?color] if it's not set. 👍 😀

@lasers
Copy link
Contributor

lasers commented Apr 6, 2017

I'm experimenting with something to see if I can keep everything in one format for whatismyip... and I'm struggling with this part. Can we use multiple ifs? I looked at test formatter and don't see any. I tried many things.

format = '[\?if=use_icon \?if=connected YES|NO]|{ip}'
format = '[\?if=icon&show \?connected YES|NO]|{ip}'

{icon}:True/False
{connected}:True/False
{ip}:127.0.0.1

EDIT: I got it... format = '\?if=!connected ■|[\?if=icon&show ●|[{ip}]]'. 💯 💯 💯
THIS IS FUUUUUU HARD!!!!!!!!!!!!! 👍

@lasers
Copy link
Contributor

lasers commented Apr 7, 2017

@tobes What should I do with this? https://github.com/lasers/py3status/blob/whatismyip-formatter/py3status/modules/whatismyip.py

I cleaned up everything. No depreciation stuffs. One format in whatismyip now. I added missing placeholders too. Just a fun experiment that I'm done with. Putting together a working format was tricky.

@maximbaz I know you like this module. What do you think of it now? Everything should be same as old whatismyip except that we don't scroll anymore so it doesn't retrieve URLs more than button_toggle clicks and/or cache_timeout. Let me know if something is off.

@maximbaz
Copy link
Contributor

maximbaz commented Apr 8, 2017

So my feedback:

  • Configuring with format is... unusual, but a fine experience, it didn't take me long to adjust the default to what I normally use. And it's nice that it's such a powerful tool.
  • the mouse is a very poor naming, it took me a while to understand what it means 😄 In reality this is a boolean that shows whether I'm in a mode1 or in a mode2, and mouse is used to toggle between modules. Even is_mode1 would be more intuitive name, in my mind...
    Or maybe (beware, crazy stuff begins), you can make it not a boolean, but integer, and call it mode, and define a parameter number_of_modes, and mouse click will rotate between the modes (so if number_of_modes = 3, mouse click makes mode=1, mode=2, mode=3, mode=1, ...). Then use format to define output for as many modes as you like, if it has capability to compare numbers 🙂

@lasers
Copy link
Contributor

lasers commented Apr 8, 2017

I renamed mouse to toggled. Better naming and to stay in consistent with button_toggle so we can name more mouse booleans if necessary.

If we add other options... like stop, mute, etc... we could use if\?=stoppped or if\?=muted. I think it may be a problem with next, prev, up, down, etc... if\?nexted, if\?=preved, if\?=upped, if\?=downed (??). I don't know.

I also don't know if that's the direction we're going with the formatter. This is a good experiment to get some ideas of whenever we want things to be like this.

I think this is nice and easy for on/off modules. This is a little crazy because I went a little crazy by omitting icons stuffs. If we get that back in, then we could go with something a little simple like \?if=toggled {icon}|[{ip}] instead.

Thanks for the feedback. 👍

@tobes
Copy link
Contributor Author

tobes commented Apr 8, 2017

My take on the whatsmyip is that is is quite crazy, I can't think of any other modules that have a mode, maybe I missed some. Anyhow I think we should look for a common approach that we can use in many places.

I like the idea of supplying multiple formats to modules eg format = ['format 1', 'format 2', ..] and cycling through them on click like we do in some other places eg clock because I think it is useful eg for battery_level I could do format = ['{icon}', '{icon} {percent} {time_remaining}'] so I can switch between summary and detailed output.

Now the multi format approach is a challenge because really if we do it we want to allow it without having to implement it for every module (because that would be a pain) So anyhow that's where I'd like to go but I don't think it is easy. But that does not really solve the whatsmyip issues.

Anyhow with the example format format = '\?if=!connected ■|[\?if=toggled&show ●|[{ip}]]' which is basically trying to do everything in one format. We should be able to simplify it by removing the &show because the if should be all that is needed. The square brackets can probably die too. The way you are passing connected, and toggled to the format is horrible but that can be cleaned up easily. My main concern is about keeping the formats, or at least the default ones easily understandable for users who are less technical.

@lasers
Copy link
Contributor

lasers commented Apr 8, 2017

format = '\?if=!connected ■|[\?if=toggled&show ●|[{ip}]]' OLD.
format = '\?if=!connected ■|[\?if=toggled ●|[{ip}]]'. NEW.
Confirmed. No &show. Thx... Still need brackets. Thx.

How should I pass connected and toggled? They seems somewhat straightforward.

I tried True/False approach first and it doesn't work. Need dicts w/o 0,1 cause if I input numbers, it shows up on the status too... so I opted for '',' ' instead... Kinda knew there would be a better solution in the future. This is neat that we trimmed, I think 30 lines, from master branch when I wc. Not sure cause of docstrings and extra placeholders. 👍

I think the screenshot have the mode too... I wanted a mode for bluetooth too. You saw that long Microsoft mouse name. Also, we probably could put mpd_status or dropbox in one format using format+control placeholders... [\?if=play... ]|[\?if=pause... ]|[\?if=stop..... ][if\?if=not_authenticated...]|[\?if=not_connected... ]. Crazy?

@tobes
Copy link
Contributor Author

tobes commented Apr 8, 2017

How should I pass connected and toggled?

Well it seems the nice way to do it is broken in master, but it works correctly in #887 and I've now added some tests to that branch. The nice way is to just set self.toggle in the module and the formatter will find it. In master you can do format = '{toggle}', but not format = '[\?if=toggle ...]'.

A fine demonstration of why #887 is amazing 🔥

@lasers
Copy link
Contributor

lasers commented Apr 8, 2017

Can confirm the nice way using DPMS's cache_timeout as a test. Ran into an issue with this... frame -> format_button_closed = '{urgent} URGENT +|+'

Composite issue? If this works, then I could drop frame: add urgent button PR, but I think it'd be nice for others if we get that merged... or make it a new default.

@lasers
Copy link
Contributor

lasers commented Aug 18, 2017

@tobes I'm making changes in gcal... and I just realized something.

We may be missing the formatter features for time stuffs too.

In gcal... I wanted to know if I should bother exposing starttime, endtime.

  • On specified events, it's fine. The times will be shown.
  • On all-day events (eg, Garbage Pickup, Prescription refill, Pick up the kids , etc)... it's just 00:00 and 00:00. I could internally remove those since it'd be stupid to keep seeing them if we can't remove them, but still see the times for the other events.
  1. OMITTED [{starttime}], [{endtime}] with 00:00... to make it disappear ?
  2. Come up with a way to turn 7:00 PM into 7 PM or 7PM ?
  • Do we do something like 1) above? (eg somehow supporting 0:00, :00, and :00 ?)
  • Otherwise, I stay with remove = [':00 '] for gcal.
  • Global sed option that allows users to strip/remove/replace... might be better?

EDIT: Hi. There won't be any timedate placeholders. We can forget about 1).

In cmus, moc, and probably others too.

Real data       |  {duration} length time in seconds, eg 171
Synthetic data  |  {durationtime} length time in [HH:]MM:SS, eg 02:51
Real data       |  {position} elapsed time in seconds, eg 17
Synthetic data  |  {positiontime} elapsed time in [HH:]MM:SS, eg 00:17

to...

Real data       |  {duration} length time in seconds, eg 171
Real data       |  {duration:s} length time in [HH:]MM:SS, eg 02:51
Real data       |  {position} elapsed time in seconds, eg 17
Real data       |  {position:s} elapsed time in [HH:]MM:SS, eg 00:17

Replace ? with time symbol.

  • Convert seconds to [HH:]MM:SS using s
  • Convert milliseconds to [HH:]MM:SS using ms
  • Add other time conversions too... for the overkill. 🥇 👍
  • Etc cetera
  • It's a bit misleading right now, but something like :s_to_hms. Idk.

I'll keep working on gcal to get rid of that year bug. I plan to support urgent too. 🔔

@lasers
Copy link
Contributor

lasers commented Aug 23, 2017

Something for the sizes?

{installed} package installed size, eg 2128558 <-- raw bytes
{filename} package filename size, eg 583304 <-- raw bytes
{installed} package installed size, eg 2.03MB  <-- hardcoded / manipulated
{filename} package filename size, eg 570KB <-- hardcoded / manipulated
{installed:bytes} package installed size, eg 2.03MB  <-- formatter ?
{filename:bytes} package filename size, eg 570KB <-- formatter ?

Not sure how we can configure the format... Maybe universal format_size?

  • format_size = '{size} {unit}' so we can print 570KB or 570 KB
  • Add more placeholders and/or configs... such as... symbol (Kb, K), short names (kibi), full names (kibibit) , lowercase (570kb), et cetera... Idk.

@lasers
Copy link
Contributor

lasers commented Sep 19, 2017

Something for the urgency hints? 🔔

format = '[\?if=percent<5&urgent Critical|[\?if=percent<15&urgent Low] {percent}'
format = '[\?if=count>1&urgent][\?not_zero Mail {count}]
format = '[\?not_zero&urgent Mail {count}] ^ Same.

@lasers
Copy link
Contributor

lasers commented Oct 3, 2017

Something for the notifications? ℹ️

format = '[\?if=percent=5&notify Critical|[\?if=percent=15&notify Low] {percent}'
format = '[\?if=count>1&notify 'You got a mail'][\?not_zero Mail {count}]

Something for the exec? ❗

format = '[\?if=percent=5&exec ~/suspend.sh shutdown|[\?if=percent=15&exec ~/suspend.sh autosave] {percent}'
format = '[\?if=count>1&exec ~/pgrep-thunderbird.sh][\?not_zero Mail {count}]

@lasers
Copy link
Contributor

lasers commented Oct 21, 2017

Reverse ellipsis is required if we want to keep window_title fully intact.

@lasers
Copy link
Contributor

lasers commented Oct 25, 2017

Something for the case conversions? 💌

  • Convert all letters to lowercase.
  • Convert all letters to uppercase.

\?upper and \?lower

{city}, eg Chicago
format = '\?upper City: {city}'  ----> 'CITY: CHICAGO'
format = '\?lower City: {city}'  ----> 'city: chicago'

{city:upper} and {city:lower}

{country}, eg Russia
format = 'Welcome to {city:upper}'  ----> 'Welcome to RUSSIA'
format = 'Welcome to {city:lower}'  ----> 'Welcome to russia'

@lasers
Copy link
Contributor

lasers commented Nov 4, 2017

Something for the timeouts? ⏲

Thought:

  • Replace cache_timeout with [\?cache=60 ]... -1 is CACHE_FOREVER.
  • Change cache_timeout via... [\?cache=10 ], [\?cache=60], [\?cache=-1], etc.
  • Change request_timeout via... [\?request=5 ]

Policy:

  • cache_timeout uses 60 or CACHE_FOREVER if unspecified.
  • request_timeout uses 10 or 15 if unspecified.

Reasons.

  • Remove simple / hardcoded timeout configs in favor of flexible timing.
  • Flexible timing to be based on data too.... same as the format rather than just a number.
  • Remove the need for timeout configs. One format to rule them all.
  • Use control placeholders to dictate timing instead of configs. Skip deadbeef: add sleep_timeout #1146

Examples using cmus:

    cache_timeout = 5
    format = '[\?if=is_started [\?if=is_playing > ][\?if=is_paused \|\| ]' +\
        '[\?if=is_stopped .. ][[{artist}][\?soft  - ][{title}]' +\
        '|\?show cmus: waiting for user input]]'
    sleep_timeout = 20

New.

    format = '[\?if=is_started [\?if=is_playing > ][\?if=is_paused \|\| ]' +\
        '[\?if=is_stopped .. ][[{artist}][\?soft  - ][{title}]' +\
        '|\?show cmus: waiting for user input]]'
    format += '[\?if=is_started&cache=5 |\?cache=20 ]'

Pro -- More choices.

    format = '[\?if=is_started [\?if=is_playing > ][\?if=is_paused \|\| ]' +\
        '[\?if=is_stopped .. ][[{artist}][\?soft  - ][{title}]' +\
        '|\?show cmus: waiting for user input]]'
    format += '[\?if=is_started&cache=15 |[\?if=is_playing&cache=1 |[\if=is_paused&cache=5 |\?cache=60 ]]'

Con -- Not user friendly.

@lasers
Copy link
Contributor

lasers commented Nov 8, 2017

Something to update the other modules? ⬆️

Random module updating other module.

format += '[\?if=is_connected&update github]'

Random module updating all modules.

format += '[\?if=is_connected&update all]'
    OR
format += '[\?if=is_connected&update ]'

@tobes
Copy link
Contributor Author

tobes commented Nov 9, 2017

@lasers I think things like the :lower are nice ideas and fit in with the formatter as a concept. However I think things like updating modules or the timeout do not really belong as part of the format. It is an interesting idea and I will have a think.

Really the main work I need to do now is provide some formatter documentation and then look at implementing some of the more straight forward ideas. Also hopefully I will get more settled and have some time for py3status. Maybe even today if I meet my targets.

@lasers
Copy link
Contributor

lasers commented Nov 9, 2017

updating modules

The module input can use this. For now, I use a config. I'm just listing them as I see them. Cheers.

the timeout

interval can be changed based on behaviors too, not just the format. Best part? Less configs.

Format placeholder:
    {format_coin} format for cryptocurrency coins

Time placeholders:
    cache:  refresh interval for this module (default 5)
    request:  time to wait for a response, in seconds (default 5)
    sleep:  sleep interval for this module (default 20)

do not really belong as part of the format

One format to rule them all. 💍

Also hopefully I will get more settled and have some time for py3status.

No problem. I hope the new situation is working out wonderful for you. 📦

@lasers
Copy link
Contributor

lasers commented Dec 12, 2017

@tobes Anything to truncate 3 chars from right side? I can with left. EDIT: Placeholder.

@lasers
Copy link
Contributor

lasers commented Jan 7, 2018

Something to report errors? This comes from #1217

Assuming (self.py3.error) error will switch to CACHE_FOREVER one day.

# stop the module permanently
format = '[\?if=status~running!&error Dropbox disabled]'
# keep running the module
format = '[\?if=status~running!&color=bad Dropbox disabled]
  • Note: ~ mean in... as in... if 'running!' in 'Dropbox isn't running!'.

@L0ric0 L0ric0 mentioned this issue Aug 17, 2018
@L0ric0
Copy link
Contributor

L0ric0 commented Aug 19, 2018

I think there is an inconsitency in the parsing of the format strings. Consider the following format string for the mpd_status module:
MPD: {state} [\?if=!state=[stop] [[[{artist}] - {title}]|[{file}]]]
The brackets around the stop are literal brackets which are used in the comparison, but in the README it is stated that literal brackets need to be escaped. I don't know if it is worth fixing this or if it is enough to mention it in the README and the documentation of the affected modules.

Oh and is it possible to add a format or condition debug mode which will print the exact comparisons done to the journal? Like:
<module_name>: if=!state=stop evaluated to [stop]=stop -> False

@lasers lasers added the enhancement 😍 I have created an enhancement label Aug 20, 2018
@tobes tobes removed the feature request 🙏 I am requesting a feature label Aug 27, 2018
@lasers lasers added feature request 🙏 I am requesting a feature and removed enhancement 😍 I have created an enhancement labels Aug 27, 2018
@lasers
Copy link
Contributor

lasers commented Jan 16, 2019

For archiving purposes... The answer to comment above is that in mpd_status, the user-configurable default states are already wrapped in brackets making it difficult to write a format string. See #1394 and/or the default states in question... (code below).

state_pause = "[pause]"
state_play = "[play]"
state_stop = "[stop]"

I think this issue has outlived its usefulness long time ago. And we have a RFC 4.0 for dropping
the formatter so we probably should not worry about this issue (i.e. new formatter features) right now.
We could always reopen this issue later too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request 🙏 I am requesting a feature
Projects
None yet
Development

No branches or pull requests

4 participants