Coder Social home page Coder Social logo

nobodyxu / swaystatus Goto Github PK

View Code? Open in Web Editor NEW
23.0 2.0 2.0 641 KB

A minimal executable for displaying sway status per second

License: MIT License

Makefile 2.97% C 15.41% Vim Script 0.46% C++ 80.00% Shell 1.12% Python 0.05%
swaywm swaybar battery sensors-reading volume brightness backlight status-bar

swaystatus's Introduction

swaystatus

A lightweight yet feature-rich status bar for i3bar or swaybar.

screenshot

It is written completely in C/C++ to make it as lightweight as possible and specifically, to avoid creating new processes every second as in bash script.

It uses libraries like libasound and glibc function getifaddrs to retrieve volume information as opposed to using amixer and ip addr.

For battery, backlight, load, and meminfo, it reads directly from /sys/class/power_supply, /sys/class/backlight, /proc/loadavg and /proc/meminfo.

Runtime Dependency

  • libasound.so.2
  • libjson-c.so.5 (also used by sway and swaybar)
  • libsensors.so.5

Build

Install clang (must have lto support), lld, make and pkg-config, then run

git clone --recurse-submodules https://github.com/NobodyXu/swaystatus
cd swaystatus/src
make -j $(nproc)

You can customize ou build via environment variable:

  • BUILD_DIR: affects where the built object will be put. Default is ..
  • TARGET_DIR: where the executable will be installed when make install is executed. Default is /usr/local/bin
  • PYTHON: whether to include embeded python interpreter support in swaystatus, can be true or false. Default is true.
  • DEBUG: whether to have a debug build or release build. true for debug build and falsefor release build. Default is false.
  • EXCEPTION: whether to enable C++ exception. false to disable C++ exception.

To install, run sudo make install, which by default will install a single binary swaystatus to /usr/local/bin.

Usage

swaybar usage:

swaystatus: Usage: swaystatus [options] configuration_filename

  --help                    Show help message and exit
  --interval=unsigned_msec  Specify update interval in milliseconds, must be an unsigner integer.
                            By default, the interval is set to 1000 ms.

To reload swaystatus, send SIGUSR1 to swaystatus process.

Config file format

{
    "order": ["network_interface", "time"],
    "_comment": "element order specify the order of which blocks will appear.",
    "_comment2": "If a block is not specified in order, it will not appear.",

    "name": {
        "format": "Hello, {variable_name}",
        "short_format": "hello", 
        "update_interval": 20,
        "color": "##RRGGBBA",
        "background: "##RRGGBBA",
        "border": "##RRGGBBA",
        "border_top": 1,
        "border_bottom": 1,
        "border_left": 1,
        "border_right": 1,
        "min_width": 1,
        "align": "center",
        "separator": true,
        "separator_block_width": 9,
        "markup": "none",

        "click_event_handler": {
            "type": "python",
            "module_name": "hello",
            "function_name": "handler"
        }
    },
    "_comment": "Any variable starts with '_' is a comment"
}

All property present for "name" above are optional.
For volume, you can also set property "mix_name" and "card".

The following values are valid name:

  • brightness

  • volume

  • battery

    The configuration block of battery support excluded_model to exclude certain battery devices from the output of swaystatus.

  • network_interface

  • load

  • memory_usage

  • time

  • sensors

Any unrecognized parameters will be ignored.

"format"

It is used internally to generate the "full_text" that will be passed to swaybar.

Formatting for blocks other than time is done using fmt - Format String Syntax.
Formatting for block time is parsed by strftime.

In the format string, user is capable of taking advantage of format variables to customize the output.

"short_format"

It is used to generate "short_text", which is used by swaybar when it decided that the "full_text" is too long.

Click Event Handling Support

TO enable click event handling for a block, add json object "click_event_handler" to the block that block.

The return value of it can be ored from the following values:

  • 0 do nothing
  • 1 force the module to update
  • 2 force the module to reload

Currently, the handler can be written in python or C/C++.

Loading python handler

For loading python handler, add "type": "python" to your "click_event_handler", then specify the "module_name" and "function_name" of the handler.

swaystatus will attempt to load the module from the same directory of your configuration file, your current working dir, any path you specified with environment variable PYTHONPATH and your system module paths.

If instead you want to embed the python code into your configuration file, add "code" to your "click_event_handler" and assign your code as value to it.

The python function is expected to have signature (Check here for more information):

(instance: str, click_pos: Tuple[int, int], button: int, event: int, relative_click_pos: Tuple[int, int], blocksize: Tuple[int, int]) -> int

Your function is expected to return 0 and any exception thrown in your function must be handled, otherwise swaystatus will print that error and exit.

Loading C/C++ handler

You C/C++ code has to be compiled with -fPIC -shared.

For loading python handler, add "type": "dynlib" to your "click_event_handler", then specify the "module_name" and "function_name" of the handler.

Just like loading python, swaystatus will attemp to load the shared library from the same directory of your configuration file, your current working dir.

It is loaded using dlopen, so LD_LIBRARY_PATH, /etc/ld.so.cache, /lib and /usr/lib is also searched.

You can also specify the path instead of a name directly in the module_name, which is perfectly valid.

The C/C++ function is expected to be exported in "C" and have signature:

#include <stdint.h>

struct Pos {
    uint64_t x;
    uint64_t y;
};
typedef struct Pos ClickPos;
typedef struct Pos BlockSize;

int f(
    const char *instance, 
    const ClickPos *pos,
    uint64_t button,
    uint64_t event,
    const ClickPos *relative_pos,
    const BlockSize *size
)

Your function is expected to return 0.

Disable block

If you want to disable a certain feature, say brightness, then add the following to your configuration:

{
    "brightness": false,
}

Or if you are using element "order" for specifing block order, then you can simply remove the name from "order".

Note that {"brightness": false} overrides "order":
If block specified in "order" is disabled by setting it to false, then the block will not appear.

custom

Using this block, you can import a python/c module and display whatever you want in this block.

You need to provide update_callback and do_print_callback, which need to have the same fields as click event handler type, module_name, function_name, (optional code for python).

Check example-config.json for example configuration of this block.

update_interval

If specified, then the block will update at update_interval * main_loop_interval ms, where main_loop_interval is the value passed by cmdline arg --interval= or 1000 ms by default.

update_interval for sensors

The sensors on computer are so many that they cannot be fitted into one line, so swaystatus instead, print one sensor each time and once update_interval is reached, next sensor is shown at the swaybar.

When all sensors are shown, swaystatus will then update the sensors reading from the computer.

Format_Variables

Battery format variables:

  • has_battery: check whether battery device exists

  • per_battery_fmt_str, which is used to print every battery on this system.

    It contains the following variables:

    • name
    • present
    • technology
    • model_name
    • manufacturer
    • serial_number
    • status
    • cycle_count
    • voltage_min_design
    • voltage_now
    • charge_full_design
    • charge_full
    • charge_now
    • capacity
    • capacity_level
    • is_charging (Check section "Conditional Variable" for usage)
    • is_discharging
    • is_not_charging
    • is_full

Memory Usage variables:

  • MemTotal
  • MemFree
  • MemAvailable
  • Buffers
  • Cached
  • SwapCached
  • Active
  • Inactive
  • Mlocked
  • SwapTotal
  • SwapFree
  • Dirty
  • Writeback
  • AnonPages
  • Mapped
  • Shmem

The unit (supports 'BKMGTPEZY') of the variables printed can be specified.
For example, '{MemTotal:K}' will print MemTotal in KiloBytes.

Volume variables:

  • volume

Load variables:

  • loadavg_1m
  • loadavg_5m
  • loadavg_15m
  • running_kthreads_cnt
  • total_kthreads_cnt
  • last_created_process_pid

Brightness variables:

NOTE that these variables are evaluated per backlight_device.

  • backlight_device
  • brightness
  • max_brightness
  • has_multiple_backlight_devices (this is a Conditional Variable)

Network Interface variables;

  • is_connected

  • is_not_connected

  • per_interface_fmt_str: The specification for this variable will be formatted once for each interface.

    It contains subvariables that can be used inside:

    • HAS_UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
    • has_broadcast_support
    • is_pointopoint
    • has_no_arp_support
    • is_in_promisc_mode
    • is_in_notrailers_mode
    • is_master
    • is_slave
    • has_multicast_support
    • has_portsel_support
    • is_automedia_active
    • is_dhcp
    • rx_packets
    • tx_packets
    • rx_bytes (Supports unit specification, checks Memry Usage Variables for more info)
    • tx_bytes (Supports unit specification, checks Memry Usage Variables for more info)
    • rx_errors
    • tx_errors
    • rx_dropped
    • tx_dropped
    • multicast
    • collisions
    • rx_length_errors
    • rx_over_errors
    • rx_crc_errors
    • rx_frame_errors
    • rx_fifo_errors
    • rx_missed_errors
    • tx_aborted_errors
    • tx_carrier_errors
    • tx_fifo_errors
    • tx_heartbeat_errors
    • tx_window_errors
    • rx_compressed
    • tx_compressed
    • ipv4_addrs
    • ipv6_addrs

    Limit of number of ip address can be done via {ipv4_addrs:1} and {ipv6_addrs:1}

    Optionally if HAS_UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO, the following variables are also defined:

    • is_lower_up
    • is_dormant
    • is_echo_device

To limit number of ip addresses in output, please use {ipv4_config:1}.

Sensors variables;

  • prefix: the name of the device
  • path: the path to the device in /sys
  • addr: the internal address of the device in libsensors
  • bus_type: the type of device
  • bus_nr: unclear
  • reading_number: the internal index for the specific sensor reading
  • reading_temp: the temperature reading from the sensor

Format string for time:

Conditional Variables

Conditional variables are used to conditionally evaulate part of the format string.

For example, setting "format" in "battery" to "{is_charging:Charging}" will print "Charging" only when the battery is charging.

All variables start with "is" and "has" are conditional variables.

Recursive Conditional Variable:

In additional to printing strings conditionally, conditional variables can also be used to print other variables conditionally.

For example, "{is_charging:{level}%}" will print "98%" when charging, where "98" is the actual level of battery.

Check example-config.json for the example configuration.

Use swaybar in sway

bar {
    status_command swaystatus
}

swaystatus's People

Contributors

nobodyxu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

swaystatus's Issues

[Feature Request] Add format variable to detect presence of battery

Is your feature request related to a problem? Please describe.

Currently on desktop, user has to manually disable battery printing.

Otherwise, swaystatus will report an error and exit.

Describe the solution you'd like

Add a format variable has_battery for detecting whether variable is present.

[Feature Request] Add format variable to detect presence of sensor readings

Is your feature request related to a problem? Please describe.

Currently, swaystatus will print out uninitialized garbage if there is no sensor reading at all.
Reading uninitialized garbage is undefined behavior and shall be fixed.

Describe the solution you'd like

Reading uninitialized data should be fixed and a format variable should be added to detect presence of sensor readings.

FTBFS visit_all_subdirs fallthrough

Describe the bug

tumbleweed-pkg/t/s/src (main)$ make CC=gcc
gcc -std=c11 -c -Wall -Wextra -Werror -O3 -flto -fno-asynchronous-unwind-tables -fno-unwind-tables -I/usr/include/json-c  -I/usr/include/python3.11 -I/usr/include/python3.11 -DUSE_PYTHON -MT alsa.o -MMD -MP -MF ./alsa.Td -o alsa.o alsa.c
mv -f ./alsa.Td ./alsa.d && touch alsa.o
gcc -std=c11 -c -Wall -Wextra -Werror -O3 -flto -fno-asynchronous-unwind-tables -fno-unwind-tables -I/usr/include/json-c  -I/usr/include/python3.11 -I/usr/include/python3.11 -DUSE_PYTHON -MT poller.o -MMD -MP -MF ./poller.Td -o poller.o poller.c
mv -f ./poller.Td ./poller.d && touch poller.o
gcc -std=c11 -c -Wall -Wextra -Werror -O3 -flto -fno-asynchronous-unwind-tables -fno-unwind-tables -I/usr/include/json-c  -I/usr/include/python3.11 -I/usr/include/python3.11 -DUSE_PYTHON -MT process_configuration.o -MMD -MP -MF ./process_configuration.Td -o process_configuration.o process_configuration.c
mv -f ./process_configuration.Td ./process_configuration.d && touch process_configuration.o
gcc -std=c11 -c -Wall -Wextra -Werror -O3 -flto -fno-asynchronous-unwind-tables -fno-unwind-tables -I/usr/include/json-c  -I/usr/include/python3.11 -I/usr/include/python3.11 -DUSE_PYTHON -MT utility.o -MMD -MP -MF ./utility.Td -o utility.o utility.c
utility.c: In function ‘visit_all_subdirs’:
utility.c:328:20: error: this statement may fall through [-Werror=implicit-fallthrough=]
  328 |                 if (!isdir(path, path_fd, ent->d_name))
      |                    ^
utility.c:331:13: note: here
  331 |             case DT_DIR:
      |             ^~~~
cc1: all warnings being treated as errors
make: *** [Makefile:76: utility.o] Error 1
tumbleweed-pkg/t/s/src (main)$

Expected behaviour
Clear build

Actual behaviour
Fails to build

Desktop (please complete the following information):

  • The Linux flavour you use: openSUSE/Tumbleweed
  • swaystatus version: master version from git
  • swaystatus configuration none

[Feature Request] Support handling click events

Click events provides a mean for user to interact with the status block. User could configure it to:

  • load a library and execute function
  • embed python interpreter inside swaystatus

User should also be able to trigger:

  • refresh of the corresponding block

[Feature Request] Support reloading upon signal

Is your feature request related to a problem? Please describe.

Currently to reload swaystatus, you have to send a reload signal sway.

Describe the solution you'd like

Register a signal handler that exec itself upon signal delivery.

Also need to close all fd except for 0, 1, and 2 in main.

[Dev] Add testing

Though it is difficult to perform testing given that the output of swaystatus highly coupled with the current state of the system,
it is still possible to at least some basic form of test for:

  • test relative/absoluate configuration loading
  • test configuration verification
  • test format by setting it to a pure string (not format string)
  • test reloading with or without configuration
  • testing click events support

[Feature Request] Add support for custom block

Support of custom block will be useful to further integrate swaystatus into users' workflow.

For example, they can add a block that monitors their git repository/servers, etc.

It can be implemented via the following manners:

  • load a library and execute function
  • embed python interpreter inside swaystatus

[BUG] Potential bug in handle_click_events when reloading

Describe the bug

It is entirely possible for click_events_handler to read in part of the event JSON object while leaving out the others, thus causing the reloaded swaystatus to fail because "Assumption on click event read from stdin fail".

Expected behavior

swaystatus should finish processing current event before reloading.

Actual behavior

swaystatus can reload before the current event is processed.

Desktop (please complete the following information):

Not related.

[Feature Request] Enable C++ exception for better error message

Is your feature request related to a problem? Please describe.

Currently, as C++ exception is disabled, fmt generate error message that are hard to understand and debug.

Adding exception handling would allow it to be caught in print_* and gives a much better error message.

Describe the solution you'd like

Enable C++ exception handling, add catch block to each print_* to catch the error and print a more readable error message.

Describe alternatives you've considered

In the branch FeatureMultipleBAT, I tried to override FMT_THROW, but it doesn't help much.

Additional context

By removing -fno-exceptions, size of binary grow by 1K.

According to google search result, the -fno-rtti flag can be kept while exception is enabled.

The exception handling would bring in required RTTI information only to the binary, keeping it small and compact.

[Feature Request] Support short format

Is your feature request related to a problem? Please describe.

Due to additional of new network interface, sometimes the output of status will be too long to fit into swaybar.

Describe the solution you'd like

Add configuration entry short_format, which is used to generate short_text

short_text | string | If given and the text needs to be shortened due to space, this will be displayed instead of full_text

The text above is copied from swaybar-protocol

[Feature Request] Add callback for dynamically adding swaybar JSON property

Is your feature request related to a problem? Please describe.

While most property for the block can be specified ahead of time, certain property like "urgent", has to be specified dynamically
and different users have different take on what is "urgent".

Also, users would like a warning to pop out to warn them of this urgent situations, so they should be able to provide their own
callback.

Describe the solution you'd like

  • python callback
  • dlopen

Describe alternatives you've considered

This feature can certainly be builtin into swaystatus, but then user will not be able to extend it as they like and swaystatus
would become much more complex, since it would also need to write UI code for implementing popup, which is best to be left
for the user to implement.

[BUG] Build Error

Description
Compiler error when trying to build master(dc196ef) on Fedora 34.

To Reproduce
Steps to reproduce the behavior:

  1. Clone Repository to system running Fedora 34
  2. cd swaystatus/src
  3. make -j4
  4. See error

Expected behavior
Build should complete without errors.

Actual behavior

handle_click_events.cc:83:40: error: use of undeclared identifier 'JSON_TOKENER_ALLOW_TRAILING_CHARS'
        json_tokener_set_flags(parser, JSON_TOKENER_ALLOW_TRAILING_CHARS);

Desktop:

  • Fedora 34
  • swaystatus version: Latest
  • json-c-devel: 0.14-8.fc34

[BUG] Quotation mark in format string needs to be escaped

Describe the bug

Since swaystatus prints the result of format directly to buffer instead of first appending it to json, it is suspectible to unescaped quotation mark.

To Reproduce

Steps to reproduce the behavior:

  1. Change element "format" of arbitrary block to "\""

Expected behavior

swaystatus should just output " for that block.

Actual behavior

swaybar failed to parse output of swaystatus.

[Feature Request] Multiple batteries

Is your feature request related to a problem? Please describe.
Yes, my feature request is related to a problem with systems with more than one battery present, be it within certain laptop models such as the ThinkPad X250 or a Bluetooth device that reports it's battery to the host operating system.
When using such a system swaystatus tends to often recognize the incorrect battery, using the options offered I was not able to solve this issue, which is why I would like to have the option to choose a specifc battery in my configuration file (as the low-level IDs used stay persistent)

Describe the solution you'd like
An ideal solution for this problem would be to implement {for_battery:BAT0} (or however you decide to make the syntax look like}. However I would still accept {per_battery_fmt_str} as it would still allow me to see the battery percentage on my laptop unlike now.

Describe alternatives you've considered
Writing a separate script for this is a waste of time in my opinion and ideally should be fixed within the software itself.

Additional context
Add any other context or screenshots about the feature request here.

Example of such an system with two batteries:

nikp123@HP-Laptop /home/nikp123 $ acpi
Battery 0: Discharging, 0%, rate information unavailable <-- my mouse (buggy, I know)
Battery 1: Unknown, 95% <-- the actual laptop
nikp123@HP-Laptop /home/nikp123 $ 

[Feature Request] Support configuring block order

Is your feature request related to a problem? Please describe.

Currently, the order of all blocks are fixed at compile time.

Describe the solution you'd like

User should be able to set the order by

{
    "order": ["network_interface", "time", ...],
    "_here goes the configuration of blocks": "",
    "network_interface": {},
    ...
}

This depends on #14.

[BUG] Doesn't compile with Python 3.11 due to deprecated functions

Describe the bug
Compiling with Python 3.11 fails

To Reproduce
Steps to reproduce the behaviour:

  1. Download Fedora 37 beta, this includes Python 3.11 rc1 ish
  2. Compile the code
  3. Get a few compile errors
  4. python3.cc:129:5: error: 'PySys_SetArgvEx' is deprecated
  5. python3.cc:145:5: error: 'Py_SetProgramName' is deprecated

Expected behavior
Compile before and after the change

Actual behavior
Fails to compile with 3.11

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.