i3pystatus icon indicating copy to clipboard operation
i3pystatus copied to clipboard

Idea: Generic status module

Open floli opened this issue 8 years ago • 12 comments

Hello, my idea is to have a generic status module that displays something like D O G S. Each letter is a status of a service, such as Dropbox, ownCloud, git-annex or a scons build job. Each letter can be either green (synced), red (syncing) or grey/white (unkown / not running).

I think something like that is not available yet and I'm happily going to implement this. However, I need some advice on how to best integrate it with i3pystatus.

  • Should each letter be displayed by it's own instantiation of the module? This has the merit that there are on_leftclick etc. are available for each letter. Or should they be displayed by a single module?
  • The status checker should be a single python function returning either -1 (red), 0 (grey) or 1 (green). My idea is to have a class like that for each status:
class MyStatus:
    def __init__(self, option):
        self.option = option

    def __call__():
        return 0

This way the config could be like:

status.register("universal_status",
                status = (MyStatus(3), "D") # Displays a D, colored based on the return value of __call__

If all letters are displayed by one module, the status would be a list of tuples instead.

I'm open for any suggestions or pointers to already existing solutions!

floli avatar Feb 20 '16 13:02 floli

Such a display is already possible. You can remove the separators between modules with hints; some modules might not support the exact state-based coloring you need, but it should be easy enough to write a patch for the modules in question.

You could for example add a dictionary setting mapping states to colors; the default would be an empty dict. Colors would be retrieved via .get(state, self.color).

enkore avatar Feb 20 '16 14:02 enkore

I see modules that do something alike, e.g. RunWatch. But I haven't found a module which takes an arbitrary python function and display status based on the return value of it.

So imo I still need to write a new status module. Either one for each service (Dropbox, ownCloud, ...) or a generic one that takes a function as an argument. I prefer the latter due to its easier customizibility.

EDIT: I could use the Shell module. The stdout is the letter and the exit code is the status. Currently the exit code supports just two states (ok == 0 and error != 0). This needs to be enhanced to support multiple states. Is that what you thought of?

floli avatar Feb 20 '16 14:02 floli

Many "modern" services (like Syncthing etc) don't provide status information in files (runwatch, file, shell), so yeah, if those can only provide status info over some kind of IPC / API, then a custom module is needed. Either in i3pystatus directly or in your config file or somewhere else (see the wiki for examples).

Your use case sounds valid / handy to me, so the "state color" idea from above seems like the way to go for existing / new modules contributed to i3pystatus.

Yes, the shell module could use some love.

enkore avatar Feb 20 '16 18:02 enkore

Thanks for your advises. You're right, getting sync status is harder then I anticipated. ownCloud provides a socket, albeit undocumented, Dropbox also a socket, haven't found any docs for that one either.

floli avatar Feb 24 '16 20:02 floli

For a desktop application (is the drop box client one?) the D-Bus interfaces might provide insight, but many proprietary applications don't provide any at all, or only those imposed by the framework used.

enkore avatar Feb 24 '16 21:02 enkore

I tried qdbusviewer-qt5 to discover the interfaces, but found nothing about owncloud or dropbox which both were running. Or is qdbusviewer not sufficient for that?

floli avatar Feb 25 '16 08:02 floli

For dropbox you might want to look at Dropbox CLI (http://www.dropboxwiki.com/tips-and-tricks/using-the-official-dropbox-command-line-interface-cli). It is a python2 script which seems to be able to do all you want.

richese avatar Feb 25 '16 11:02 richese

Oh, yes, Found that one and somehow missed it still. Could you send me the output of ./dropbox.py status and your systems locale? The script always seems to respond on the client locale, not in the locale of the caller. So, even after an unset LANG it responds to me in German.

floli avatar Feb 25 '16 17:02 floli

There are more locale variables than LANG, see locale and locale(1) (also 5, 7)

enkore avatar Feb 25 '16 17:02 enkore

Yeah, I know. But I have only LANG set.

florian@horus ~ % unset LANG
florian@horus ~ % locale
LANG=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

floli avatar Feb 25 '16 21:02 floli

dropbox.py is open source (GPL), so if the CLI doesn't work well for parameter extraction, you could also try extracting the protocol from it.

However, you will need to re-implement the required parts yourself (and glancing over dropbox.py that's probably a good idea anyway), I don't think I can include GPL-code into this MIT project.

enkore avatar Feb 25 '16 21:02 enkore

Hey,

I have some code at https://github.com/floli/i3pystatus/tree/genericstatus

Dropbox and a Process Watcher are working.

Dropbox is using the dropbox.py script and works for german locale only. I don't think that's related the script itself but rather the dropbox daemon which returns localized messages.

The code is very simple. It's a Flostatus module which takes a callable. This callable can return -1 (red), 0 (grey) or 1 (green). The callable can be a class with call and optionally a toggle() method or a simple function.

My current configuration looks like that:

from i3pystatus.flostatus import *
status.register("flostatus",
                function = Dropbox(),
                text = "D")
status.register("flostatus",
                function = ProcessWatch("python2 /usr/bin/scons", False),
                text = "S")

I'm happy for any comments about the general concept.

I'm not sure if imports from modules are undesired. I think this is pretty pythonic, but I'm open to other ways...

floli avatar Mar 04 '16 14:03 floli