Add detached_down option (#26)

And some other stuff I obviously forget to commit last time.
Oh, that's just the RST port... okay :)
This commit is contained in:
enkore 2014-01-16 13:39:17 +01:00
parent e9e6dd1bf6
commit aa09079903
13 changed files with 395 additions and 370 deletions

View File

@ -1,15 +1,15 @@
<!-- .. Always edit README.tpl.md and create README.md by running
Always edit README.tpl.md and create README.md by running python -m i3pystatus.mkdocs You can also let the maintainer do the
python -m i3pystatus.mkdocs latter :)
You can also let the maintainer do the latter :)
-->
# i3pystatus i3pystatus
==========
i3pystatus is a (hopefully growing) collection of python scripts for i3pystatus is a (hopefully growing) collection of python scripts for
status output compatible to i3status / i3bar of the i3 window manager. status output compatible to i3status / i3bar of the i3 window manager.
## Installation Installation
------------
Note: i3pystatus requires Python 3.2 or newer and is not compatible with Note: i3pystatus requires Python 3.2 or newer and is not compatible with
Python 2.x. Python 2.x.
@ -22,9 +22,11 @@ Python 2.x.
* [Arch Linux](https://aur.archlinux.org/packages/i3pystatus-git/) * [Arch Linux](https://aur.archlinux.org/packages/i3pystatus-git/)
### Release Notes Release Notes
-------------
#### 3.28 3.28 (not released yet)
+++++++++++++++++++++++
* **If you're currently using the `i3pystatus` command to run your i3bar**: * **If you're currently using the `i3pystatus` command to run your i3bar**:
Replace `i3pystatus` command in your i3 configuration with `python ~/path/to/your/i3pystatus.py` Replace `i3pystatus` command in your i3 configuration with `python ~/path/to/your/i3pystatus.py`
@ -33,33 +35,40 @@ Python 2.x.
* pulseaudio: changed context name to "i3pystatus_pulseaudio" * pulseaudio: changed context name to "i3pystatus_pulseaudio"
* Code changes * Code changes
#### 3.27 3.27
++++
* Add weather module * Add weather module
* Add text module * Add text module
* PulseAudio module: Add muted/unmuted options * PulseAudio module: Add muted/unmuted options
#### 3.26 3.26
++++
* Add mem module * Add mem module
#### 3.24 3.24
++++
**This release introduced changes that may require manual changes to your **This release introduced changes that may require manual changes to your
configuration file** configuration file**
* Introduced TimeWrapper * Introduced TimeWrapper
* battery module: removed remaining_\* formatters in favor of TimeWrapper, * battery module: removed remaining\_* formatters in favor of
as it can not only reproduce all the variants removed, but can do much more. TimeWrapper, as it can not only reproduce all the variants removed,
but can do much more.
* mpd: Uses TimeWrapper for song_length, song_elapsed * mpd: Uses TimeWrapper for song_length, song_elapsed
## Configuration Configuration
-------------
The config file is just a normal Python script. The config file is just a normal Python script.
A simple configuration file could look like this (note the additional dependencies A simple configuration file could look like this (note the additional dependencies
from network, wireless and pulseaudio in this example): from network, wireless and pulseaudio in this example):
::
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import subprocess import subprocess
@ -165,6 +174,8 @@ from network, wireless and pulseaudio in this example):
Also change your i3wm config to the following: Also change your i3wm config to the following:
::
# i3bar # i3bar
bar { bar {
status_command python ~/.path/to/your/config/file.py status_command python ~/.path/to/your/config/file.py
@ -172,23 +183,26 @@ Also change your i3wm config to the following:
workspace_buttons yes workspace_buttons yes
} }
### Formatting Formatting
++++++++++
All modules let you specifiy the exact output formatting using a All modules let you specifiy the exact output formatting using a
[format string](http://docs.python.org/3/library/string.html#formatstrings), which [format string](http://docs.python.org/3/library/string.html#formatstrings), which
gives you a great deal of flexibility. gives you a great deal of flexibility.
Some common stuff: If a module gives you a float, it probably has a ton of
uninteresting decimal places. Use `{somefloat:.0f}` to get the integer
value, `{somefloat:0.2f}` gives you two decimal places after the
decimal dot
* If a module gives you a float, it probably has a ton of uninteresting decimal formatp
places. Use `{somefloat:.0f}` to get the integer value, `{somefloat:0.2f}` gives ~~~~~~~
you two decimal places after the decimal dot
#### formatp
Some modules use an extended format string syntax (the mpd module, for example). Some modules use an extended format string syntax (the mpd module, for example).
Given the format string below the output adapts itself to the available data. Given the format string below the output adapts itself to the available data.
::
[{artist}/{album}/]{title}{status} [{artist}/{album}/]{title}{status}
Only if both the artist and album is known they're displayed. If only one or none Only if both the artist and album is known they're displayed. If only one or none
@ -202,7 +216,8 @@ Inside a group always all format specifiers must evaluate to true (logical and).
You can nest groups. The inner group will only become part of the output if both You can nest groups. The inner group will only become part of the output if both
the outer group and the inner group are eligible for output. the outer group and the inner group are eligible for output.
#### TimeWrapper TimeWrapper
~~~~~~~~~~~
Some modules that output times use TimeWrapper to format these. TimeWrapper is Some modules that output times use TimeWrapper to format these. TimeWrapper is
a mere extension of the standard formatting method. a mere extension of the standard formatting method.
@ -211,54 +226,34 @@ The time format that should be used is specified using the format specifier, i.e
with some_time being 3951 seconds a format string like `{some_time:%h:%m:%s}` with some_time being 3951 seconds a format string like `{some_time:%h:%m:%s}`
would produce `1:5:51` would produce `1:5:51`
* `%h`, `%m` and `%s` are the hours, minutes and seconds without leading zeros * `%h`, `%m` and `%s` are the hours, minutes and seconds without
(i.e. 0 to 59 for minutes and seconds) leading zeros (i.e. 0 to 59 for minutes and seconds)
* `%H`, `%M` and `%S` are padded with a leading zero to two digits, i.e. 00 to 59 * `%H`, `%M` and `%S` are padded with a leading zero to two digits,
* `%l` and `%L` produce hours non-padded and padded but only if hours is not zero. i.e. 00 to 59
If the hours are zero it produces an empty string. * `%l` and `%L` produce hours non-padded and padded but only if hours
is not zero. If the hours are zero it produces an empty string.
* `%%` produces a literal % * `%%` produces a literal %
* `%E` (only valid on beginning of the string) if the time is null, don't format * `%E` (only valid on beginning of the string) if the time is null,
anything but rather produce an empty string. If the time is non-null it is don't format anything but rather produce an empty string. If the
removed from the string. time is non-null it is removed from the string.
* When the module in question also uses formatp, 0 seconds counts as "not known". * When the module in question also uses formatp, 0 seconds counts as
* The formatted time is stripped, i.e. spaces on both ends of the result are removed "not known".
* The formatted time is stripped, i.e. spaces on both ends of the
result are removed
## Modules Modules
-------
System: :System: `clock`_ - `disk`_ - `load`_ - `mem`_
[Clock](#clock) - :Audio: `alsa`_ - `pulseaudio`_
[Free space](#disk) - :Hardware: `battery`_ - `backlight`_ - `temp`_
[System load](#load) - :Network: `network`_ - `wireless`_
[Memory usage](#mem) :Other: `mail`_ - `parcel`_ - `pyload`_ - `weather`_ - `mpd`_ - `text`_
:Advanced: `file`_ - `regex`_ - `runwatch`_
Audio:
[ALSA](#alsa) -
[PulseAudio](#pulseaudio)
Hardware:
[Battery](#battery) -
[Screen brightness](#backlight) -
[CPU temperature (Intel)](#temp)
Network:
[Wired](#network) -
[Wireless](#wireless)
Other:
[Unread mail](#mail) -
[Tracking parcels](#parcel) -
[pyLoad](#pyload) -
[Weather](#weather) -
[Music Player Daemon (MPD)](#mpd) -
[Simple text](#text)
Advanced:
[Rip info from files](#file) -
[Regular expressions](#regex) -
[Run watcher](#runwatch)
### alsa alsa
++++
Shows volume of ALSA mixer. You can also use this for inputs, btw. Shows volume of ALSA mixer. You can also use this for inputs, btw.
@ -273,21 +268,22 @@ Available formatters:
* `{mixer}` — the associated ALSA mixer * `{mixer}` — the associated ALSA mixer
__Settings:__ Settings:
* `format` — (default: `♪: {volume}`) :format: (default: '♪: {volume}')
* `mixer` — ALSA mixer (default: `Master`) :mixer: ALSA mixer (default: 'Master')
* `mixer_id` — ALSA mixer id (default: `0`) :mixer_id: ALSA mixer id (default: '0')
* `card` — ALSA sound card (default: `0`) :card: ALSA sound card (default: '0')
* `muted` — (default: `M`) :muted: (default: 'M')
* `unmuted` — (default: ``) :unmuted: (default: '')
* `color_muted` — (default: `#AAAAAA`) :color_muted: (default: '#AAAAAA')
* `color` — (default: `#FFFFFF`) :color: (default: '#FFFFFF')
* `channel` — (default: `0`) :channel: (default: '0')
### backlight backlight
+++++++++
Screen backlight info Screen backlight info
@ -298,15 +294,16 @@ Available formatters:
* `{percentage}` — current brightness in percent * `{percentage}` — current brightness in percent
__Settings:__ Settings:
* `format` — format string, formatters: brightness, max_brightness, percentage (default: `{brightness}/{max_brightness}`) :format: format string, formatters: brightness, max_brightness, percentage (default: '{brightness}/{max_brightness}')
* `backlight` — backlight, see `/sys/class/backlight/` (default: `acpi_video0`) :backlight: backlight, see `/sys/class/backlight/` (default: 'acpi_video0')
* `color` — (default: `#FFFFFF`) :color: (default: '#FFFFFF')
### battery battery
+++++++
This class uses the /sys/class/power_supply/…/uevent interface to check for the This class uses the /sys/class/power_supply/…/uevent interface to check for the
@ -322,32 +319,34 @@ Available formatters:
* `{battery_ident}` — the same as the setting * `{battery_ident}` — the same as the setting
__Settings:__ Settings:
* `battery_ident` — The name of your battery, usually BAT0 or BAT1 (default: `BAT0`) :battery_ident: The name of your battery, usually BAT0 or BAT1 (default: 'BAT0')
* `format` — (default: `{status} {remaining}`) :format: (default: '{status} {remaining}')
* `alert` — Display a libnotify-notification on low battery (default: `False`) :alert: Display a libnotify-notification on low battery (default: 'False')
* `alert_percentage` — (default: `10`) :alert_percentage: (default: '10')
* `alert_format_title` — The title of the notification, all formatters can be used (default: `Low battery`) :alert_format_title: The title of the notification, all formatters can be used (default: 'Low battery')
* `alert_format_body` — The body text of the notification, all formatters can be used (default: `Battery {battery_ident} has only {percentage:.2f}% ({remaining:%E%hh:%Mm}) remaining!`) :alert_format_body: The body text of the notification, all formatters can be used (default: 'Battery {battery_ident} has only {percentage:.2f}% ({remaining:%E%hh:%Mm}) remaining!')
* `path` — Override the default-generated path (default: `None`) :path: Override the default-generated path (default: 'None')
* `status` — A dictionary mapping ('DIS', 'CHR', 'FULL') to alternative names (default: `{'FULL': 'FULL', 'DIS': 'DIS', 'CHR': 'CHR'}`) :status: A dictionary mapping ('DIS', 'CHR', 'FULL') to alternative names (default: '{'FULL': 'FULL', 'DIS': 'DIS', 'CHR': 'CHR'}')
### clock clock
+++++
This class shows a clock This class shows a clock
__Settings:__ Settings:
* `format` — stftime format string, `None` means to use the default, locale-dependent format (default: `None`) :format: stftime format string, `None` means to use the default, locale-dependent format (default: 'None')
### disk disk
++++
Gets `{used}`, `{free}`, `{available}` and `{total}` amount of bytes on the given mounted filesystem. Gets `{used}`, `{free}`, `{available}` and `{total}` amount of bytes on the given mounted filesystem.
@ -356,57 +355,62 @@ These values can also be expressed in percentages with the `{percentage_used}`,
and `{percentage_avail}` formats. and `{percentage_avail}` formats.
__Settings:__ Settings:
* `format` — (default: `{free}/{avail}`) :format: (default: '{free}/{avail}')
* `path` — (required) :path: (required)
* `divisor` — divide all byte values by this value, commonly 1024**3 (gigabyte) (default: `1073741824`) :divisor: divide all byte values by this value, commonly 1024**3 (gigabyte) (default: '1073741824')
### file file
++++
Rip information from text files Rip information from text files
components is a dict of pairs of the form: components is a dict of pairs of the form:
::
name => (callable, file) name => (callable, file)
* Where `name` is a valid identifier, which is used in the format string to access * Where `name` is a valid identifier, which is used in the format string to access
the value of that component. the value of that component.
* `callable` is some callable to convert the contents of `file`. A common choice is * `callable` is some callable to convert the contents of `file`. A common choice is
float or int. float or int.
* `file` names a file, relative to `base_path`. * `file` names a file, relative to `base_path`.
transforms is a optional dict of callables taking a single argument (a dictionary containing the values transforms is a optional dict of callables taking a single argument (a dictionary containing the values
of all components). The return value is bound to the key. of all components). The return value is bound to the key.
__Settings:__ Settings:
* `format` — (required) :format: (required)
* `components` — (required) :components: (required)
* `transforms` — (default: `{}`) :transforms: (default: '{}')
* `base_path` — (default: `/`) :base_path: (default: '/')
* `color` — (default: `#FFFFFF`) :color: (default: '#FFFFFF')
* `interval` — (default: `5`) :interval: (default: '5')
### load load
++++
Shows system load Shows system load
__Settings:__ Settings:
* `format`format string used for output. {avg1}, {avg5} and {avg15} are the load average of the last one, five and fifteen minutes, respectively. {tasks} is the number of tasks (i.e. 1/285, which indiciates that one out of 285 total tasks is runnable). (default: `{avg1} {avg5}`) :format: format string used for output. {avg1}, {avg5} and {avg15} are the load average of the last one, five and fifteen minutes, respectively. {tasks} is the number of tasks (i.e. 1/285, which indiciates that one out of 285 total tasks is runnable). (default: '{avg1} {avg5}')
### mail mail
++++
Generic mail checker Generic mail checker
@ -414,73 +418,77 @@ Generic mail checker
The `backends` setting determines the backends to use. Currently available are: The `backends` setting determines the backends to use. Currently available are:
__Settings:__ Settings:
* `backends` — List of backends (instances of `i3pystatus.mail.xxx.zzz`) :backends: List of backends (instances of `i3pystatus.mail.xxx.zzz`)
* `color` — (default: `#ffffff`) :color: (default: '#ffffff')
* `color_unread` — (default: `#ff0000`) :color_unread: (default: '#ff0000')
* `format` — (default: `{unread} new email`) :format: (default: '{unread} new email')
* `format_plural` — (default: `{unread} new emails`) :format_plural: (default: '{unread} new emails')
* `hide_if_null` — Don't output anything if there are no new mails (default: `True`) :hide_if_null: Don't output anything if there are no new mails (default: 'True')
Currently available backends are: Currently available backends are:
> ### imap.IMAP imap.IMAP
> ~~~~~~~~~
>
> Checks for mail on a IMAP server
>
>
> __Settings:__
>
> * `host` — (required)
> * `port` — (default: `993`)
> * `username` — (required)
> * `password` — (required)
> * `ssl` — (default: `True`)
> * `mailbox` — (default: `INBOX`)
>
>
>
> ### notmuchmail.Notmuch
>
>
> This class uses the notmuch python bindings to check for the
> number of messages in the notmuch database with the tags "inbox"
> and "unread"
>
>
> __Settings:__
>
> * `db_path` — (required)
>
>
>
> ### thunderbird.Thunderbird
>
>
> This class listens for dbus signals emitted by
> the dbus-sender extension for thunderbird.
>
> Requires
> * python-dbus
>
>
> __Settings:__
>
>
>
>
>
### mem
Checks for mail on a IMAP server
Settings:
:host: (required)
:port: (default: '993')
:username: (required)
:password: (required)
:ssl: (default: 'True')
:mailbox: (default: 'INBOX')
notmuchmail.Notmuch
~~~~~~~~~~~~~~~~~~~
This class uses the notmuch python bindings to check for the
number of messages in the notmuch database with the tags "inbox"
and "unread"
Settings:
:db_path: (required)
thunderbird.Thunderbird
~~~~~~~~~~~~~~~~~~~~~~~
This class listens for dbus signals emitted by
the dbus-sender extension for thunderbird.
Requires python-dbus
Settings:
mem
+++
Shows memory load Shows memory load
Available formatters: Available formatters:
* {avail_mem} * {avail_mem}
* {percent_used_mem} * {percent_used_mem}
* {used_mem} * {used_mem}
@ -489,39 +497,42 @@ Available formatters:
Requires psutil (from PyPI) Requires psutil (from PyPI)
__Settings:__ Settings:
* `format` — format string used for output. (default: `{avail_mem} MB`) :format: format string used for output. (default: '{avail_mem} MB')
### modsde modsde
++++++
This class returns i3status parsable output of the number of This class returns i3status parsable output of the number of
unread posts in any bookmark in the mods.de forums. unread posts in any bookmark in the mods.de forums.
__Settings:__ Settings:
* `format` — Use {unread} as the formatter for number of unread posts (default: `{unread} new posts in bookmarks`) :format: Use {unread} as the formatter for number of unread posts (default: '{unread} new posts in bookmarks')
* `offset` — subtract number of posts before output (default: `0`) :offset: subtract number of posts before output (default: '0')
* `color` — (default: `#7181fe`) :color: (default: '#7181fe')
* `username` — (required) :username: (required)
* `password` — (required) :password: (required)
### mpd mpd
+++
Displays various information from MPD (the music player daemon) Displays various information from MPD (the music player daemon)
Available formatters (uses formatp) Available formatters (uses `formatp`_)
* `{title}` — (the title of the current song) * `{title}` — (the title of the current song)
* `{album}` — (the album of the current song, can be an empty string (e.g. for online streams)) * `{album}` — (the album of the current song, can be an empty string (e.g. for online streams))
* `{artist}` — (can be empty, too) * `{artist}` — (can be empty, too)
* `{song_elapsed}` — (Position in the currently playing song, **uses TimeWrapper**, default is `%m:%S`) * `{song_elapsed}` — (Position in the currently playing song, uses `TimeWrapper`_, default is `%m:%S`)
* `{song_length}` — (Length of the current song, same as song_elapsed) * `{song_length}` — (Length of the current song, same as song_elapsed)
* `{pos}` — (Position of current song in playlist, one-based) * `{pos}` — (Position of current song in playlist, one-based)
* `{len}` — (Songs in playlist) * `{len}` — (Songs in playlist)
@ -532,16 +543,17 @@ Available formatters (uses formatp)
Left click on the module play/pauses, right click (un)mutes. Left click on the module play/pauses, right click (un)mutes.
__Settings:__ Settings:
* `host` — (default: `localhost`) :host: (default: 'localhost')
* `port` — MPD port (default: `6600`) :port: MPD port (default: '6600')
* `format` — formatp string (default: `{title} {status}`) :format: formatp string (default: '{title} {status}')
* `status` — Dictionary mapping pause, play and stop to output (default: `{'pause': '▷', 'stop': '◾', 'play': '▶'}`) :status: Dictionary mapping pause, play and stop to output (default: '{'play': '▶', 'stop': '◾', 'pause': '▷'}')
### network network
+++++++
Display network information about a interface. Display network information about a interface.
@ -549,6 +561,7 @@ Display network information about a interface.
Requires the PyPI package `netifaces-py3`. Requires the PyPI package `netifaces-py3`.
Available formatters: Available formatters:
* `{interface}` — same as setting * `{interface}` — same as setting
* `{name}` — same as setting * `{name}` — same as setting
* `{v4}` — IPv4 address * `{v4}` — IPv4 address
@ -562,55 +575,61 @@ Available formatters:
Not available addresses (i.e. no IPv6 connectivity) are replaced with empty strings. Not available addresses (i.e. no IPv6 connectivity) are replaced with empty strings.
__Settings:__ Settings:
* `interface` — Interface to obtain information for (default: `eth0`) :interface: Interface to obtain information for (default: 'eth0')
* `format_up` — (default: `{interface}: {v4}`) :format_up: (default: '{interface}: {v4}')
* `color_up` — (default: `#00FF00`) :color_up: (default: '#00FF00')
* `format_down` — (default: `{interface}`) :format_down: (default: '{interface}')
* `color_down` — (default: `#FF0000`) :color_down: (default: '#FF0000')
* `name` — (default: `eth0`) :detached_down: If the interface doesn't exist, display it as if it were down (default: 'False')
:name: (default: 'eth0')
### parcel parcel
++++++
__Settings:__ Settings:
* `instance` — Tracker instance :instance: Tracker instance
* `format` — (default: `{name}:{progress}`) :format: (default: '{name}:{progress}')
* `name` :name:
### pulseaudio pulseaudio
++++++++++
Shows volume of default PulseAudio sink (output). Shows volume of default PulseAudio sink (output).
Available formatters: Available formatters:
* `{volume}` — volume in percent (0...100) * `{volume}` — volume in percent (0...100)
* `{db}` — volume in decibels relative to 100 %, i.e. 100 % = 0 dB, 50 % = -18 dB, 0 % = -infinity dB * `{db}` — volume in decibels relative to 100 %, i.e. 100 % = 0 dB, 50 % = -18 dB, 0 % = -infinity dB
(the literal value for -infinity is `-∞`) (the literal value for -infinity is `-∞`)
* `{muted}` — the value of one of the `muted` or `unmuted` settings * `{muted}` — the value of one of the `muted` or `unmuted` settings
__Settings:__ Settings:
* `format` — (default: `♪: {volume}`) :format: (default: '♪: {volume}')
* `muted` — (default: `M`) :muted: (default: 'M')
* `unmuted` — (default: ``) :unmuted: (default: '')
### pyload pyload
++++++
Shows pyLoad status Shows pyLoad status
Available formatters: Available formatters:
* `{captcha}` (see captcha_true and captcha_false, which are the values filled in for this formatter) * `{captcha}` (see captcha_true and captcha_false, which are the values filled in for this formatter)
* `{progress}` (average over all running downloads) * `{progress}` (average over all running downloads)
* `{progress_all}` (percentage of completed files/links in queue) * `{progress_all}` (percentage of completed files/links in queue)
@ -620,20 +639,21 @@ Available formatters:
* `{free_space}` (free space in download directory in gigabytes) * `{free_space}` (free space in download directory in gigabytes)
__Settings:__ Settings:
* `address` — Address of pyLoad webinterface (default: `http://127.0.0.1:8000`) :address: Address of pyLoad webinterface (default: 'http://127.0.0.1:8000')
* `format` — (default: `{captcha} {progress_all:.1f}% {speed:.1f} kb/s`) :format: (default: '{captcha} {progress_all:.1f}% {speed:.1f} kb/s')
* `captcha_true` — (default: `Captcha waiting`) :captcha_true: (default: 'Captcha waiting')
* `captcha_false` — (default: ``) :captcha_false: (default: '')
* `download_true` — (default: `Downloads enabled`) :download_true: (default: 'Downloads enabled')
* `download_false` — (default: `Downloads disabled`) :download_false: (default: 'Downloads disabled')
* `username` — (required) :username: (required)
* `password` — (required) :password: (required)
### regex regex
+++++
Simple regex file watcher Simple regex file watcher
@ -641,16 +661,17 @@ Simple regex file watcher
The groups of the regex are passed to the format string as positional arguments. The groups of the regex are passed to the format string as positional arguments.
__Settings:__ Settings:
* `format` — format string used for output (default: `{0}`) :format: format string used for output (default: '{0}')
* `regex` — (required) :regex: (required)
* `file` — file to search for regex matches :file: file to search for regex matches
* `flags` — Python.re flags (default: `0`) :flags: Python.re flags (default: '0')
### runwatch runwatch
++++++++
Expands the given path using glob to a pidfile and checks Expands the given path using glob to a pidfile and checks
@ -662,18 +683,19 @@ such as a VPN client or your DHCP client is running.
Available formatters are {pid} and {name}. Available formatters are {pid} and {name}.
__Settings:__ Settings:
* `format_up` — (default: `{name}`) :format_up: (default: '{name}')
* `format_down` — (default: `{name}`) :format_down: (default: '{name}')
* `color_up` — (default: `#00FF00`) :color_up: (default: '#00FF00')
* `color_down` — (default: `#FF0000`) :color_down: (default: '#FF0000')
* `path` — (required) :path: (required)
* `name` — (required) :name: (required)
### temp temp
++++
Shows CPU temperature of Intel processors Shows CPU temperature of Intel processors
@ -681,49 +703,53 @@ Shows CPU temperature of Intel processors
AMD is currently not supported as they can only report a relative temperature, which is pretty useless AMD is currently not supported as they can only report a relative temperature, which is pretty useless
__Settings:__ Settings:
* `format`format string used for output. {temp} is the temperature in degrees celsius, {critical} and {high} are the trip point temps. (default: `{temp} °C`) :format: format string used for output. {temp} is the temperature in degrees celsius, {critical} and {high} are the trip point temps. (default: '{temp} °C')
* `color` — (default: `#FFFFFF`) :color: (default: '#FFFFFF')
* `color_critical` — (default: `#FF0000`) :color_critical: (default: '#FF0000')
* `high_factor` — (default: `0.7`) :high_factor: (default: '0.7')
### text text
++++
Display static, colored text. Display static, colored text.
__Settings:__ Settings:
* `text` — (required) :text: (required)
* `color` — HTML color code #RRGGBB (default: `None`) :color: HTML color code #RRGGBB (default: 'None')
### weather weather
+++++++
This module gets the weather from weather.com using pywapi module This module gets the weather from weather.com using pywapi module
First, you need to get the code for the location from the www.weather.com First, you need to get the code for the location from the www.weather.com
Available formatters: Available formatters:
{current_temp}
{humidity} * {current_temp}
* {humidity}
Requires pywapi from PyPI. Requires pywapi from PyPI.
__Settings:__ Settings:
* `location_code` — (required) :location_code: (required)
* `units` — *C*elsius or *F*ahrenheit (default: `C`) :units: Celsius (C) or Fahrenheit (F) (default: 'C')
* `format` — (default: `{current_temp}`) :format: (default: '{current_temp}')
### wireless wireless
++++++++
Display network information about a interface. Display network information about a interface.
@ -731,37 +757,41 @@ Display network information about a interface.
Requires the PyPI packages `netifaces-py3` and `basiciw`. Requires the PyPI packages `netifaces-py3` and `basiciw`.
This is based on the network module, so all options and formatters are This is based on the network module, so all options and formatters are
the same, except for these additional formatters: the same, except for these additional formatters and that detached_down doesn't work.
* `{essid}` — ESSID of currently connected wifi * `{essid}` — ESSID of currently connected wifi
* `{freq}` — Current frequency * `{freq}` — Current frequency
* `{quality}` — Link quality in percent * `{quality}` — Link quality in percent
__Settings:__ Settings:
* `interface` — Interface to obtain information for (default: `wlan0`) :interface: Interface to obtain information for (default: 'wlan0')
* `format_up` — (default: `{interface}: {v4}`) :format_up: (default: '{interface}: {v4}')
* `color_up` — (default: `#00FF00`) :color_up: (default: '#00FF00')
* `format_down` — (default: `{interface}`) :format_down: (default: '{interface}')
* `color_down` — (default: `#FF0000`) :color_down: (default: '#FF0000')
* `name` — (default: `eth0`) :detached_down: If the interface doesn't exist, display it as if it were down (default: 'False')
:name: (default: 'eth0')
### xrandr xrandr
++++++
Do Not Publish, private hack of it's own Do Not Publish, private hack of it's own
__Settings:__ Settings:
## Contribute Contribute
----------
To contribute a module, make sure it uses one of the Module classes. Most modules To contribute a module, make sure it uses one of the Module classes. Most modules
use IntervalModule, which just calls a function repeatedly in a specified interval. use IntervalModule, which just calls a function repeatedly in a specified interval.
@ -771,8 +801,3 @@ the protocol is documented [here](http://i3wm.org/docs/i3bar-protocol.html).
**Patches and pull requests are very welcome :-)** **Patches and pull requests are very welcome :-)**
### The README
The README.md file is generated from the README.tpl.md file; only edit the latter
and run `python -m i3pystatus.mkdocs`.

View File

@ -1,15 +1,15 @@
<!-- .. Always edit README.tpl.md and create README.md by running
Always edit README.tpl.md and create README.md by running python -m i3pystatus.mkdocs You can also let the maintainer do the
python -m i3pystatus.mkdocs latter :)
You can also let the maintainer do the latter :)
-->
# i3pystatus i3pystatus
==========
i3pystatus is a (hopefully growing) collection of python scripts for i3pystatus is a (hopefully growing) collection of python scripts for
status output compatible to i3status / i3bar of the i3 window manager. status output compatible to i3status / i3bar of the i3 window manager.
## Installation Installation
------------
Note: i3pystatus requires Python 3.2 or newer and is not compatible with Note: i3pystatus requires Python 3.2 or newer and is not compatible with
Python 2.x. Python 2.x.
@ -22,9 +22,11 @@ Python 2.x.
* [Arch Linux](https://aur.archlinux.org/packages/i3pystatus-git/) * [Arch Linux](https://aur.archlinux.org/packages/i3pystatus-git/)
### Release Notes Release Notes
-------------
#### 3.28 3.28 (not released yet)
+++++++++++++++++++++++
* **If you're currently using the `i3pystatus` command to run your i3bar**: * **If you're currently using the `i3pystatus` command to run your i3bar**:
Replace `i3pystatus` command in your i3 configuration with `python ~/path/to/your/i3pystatus.py` Replace `i3pystatus` command in your i3 configuration with `python ~/path/to/your/i3pystatus.py`
@ -33,33 +35,40 @@ Python 2.x.
* pulseaudio: changed context name to "i3pystatus_pulseaudio" * pulseaudio: changed context name to "i3pystatus_pulseaudio"
* Code changes * Code changes
#### 3.27 3.27
++++
* Add weather module * Add weather module
* Add text module * Add text module
* PulseAudio module: Add muted/unmuted options * PulseAudio module: Add muted/unmuted options
#### 3.26 3.26
++++
* Add mem module * Add mem module
#### 3.24 3.24
++++
**This release introduced changes that may require manual changes to your **This release introduced changes that may require manual changes to your
configuration file** configuration file**
* Introduced TimeWrapper * Introduced TimeWrapper
* battery module: removed remaining_\* formatters in favor of TimeWrapper, * battery module: removed remaining\_* formatters in favor of
as it can not only reproduce all the variants removed, but can do much more. TimeWrapper, as it can not only reproduce all the variants removed,
but can do much more.
* mpd: Uses TimeWrapper for song_length, song_elapsed * mpd: Uses TimeWrapper for song_length, song_elapsed
## Configuration Configuration
-------------
The config file is just a normal Python script. The config file is just a normal Python script.
A simple configuration file could look like this (note the additional dependencies A simple configuration file could look like this (note the additional dependencies
from network, wireless and pulseaudio in this example): from network, wireless and pulseaudio in this example):
::
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import subprocess import subprocess
@ -165,6 +174,8 @@ from network, wireless and pulseaudio in this example):
Also change your i3wm config to the following: Also change your i3wm config to the following:
::
# i3bar # i3bar
bar { bar {
status_command python ~/.path/to/your/config/file.py status_command python ~/.path/to/your/config/file.py
@ -172,23 +183,26 @@ Also change your i3wm config to the following:
workspace_buttons yes workspace_buttons yes
} }
### Formatting Formatting
++++++++++
All modules let you specifiy the exact output formatting using a All modules let you specifiy the exact output formatting using a
[format string](http://docs.python.org/3/library/string.html#formatstrings), which [format string](http://docs.python.org/3/library/string.html#formatstrings), which
gives you a great deal of flexibility. gives you a great deal of flexibility.
Some common stuff: If a module gives you a float, it probably has a ton of
uninteresting decimal places. Use `{somefloat:.0f}` to get the integer
value, `{somefloat:0.2f}` gives you two decimal places after the
decimal dot
* If a module gives you a float, it probably has a ton of uninteresting decimal formatp
places. Use `{somefloat:.0f}` to get the integer value, `{somefloat:0.2f}` gives ~~~~~~~
you two decimal places after the decimal dot
#### formatp
Some modules use an extended format string syntax (the mpd module, for example). Some modules use an extended format string syntax (the mpd module, for example).
Given the format string below the output adapts itself to the available data. Given the format string below the output adapts itself to the available data.
::
[{artist}/{album}/]{title}{status} [{artist}/{album}/]{title}{status}
Only if both the artist and album is known they're displayed. If only one or none Only if both the artist and album is known they're displayed. If only one or none
@ -202,7 +216,8 @@ Inside a group always all format specifiers must evaluate to true (logical and).
You can nest groups. The inner group will only become part of the output if both You can nest groups. The inner group will only become part of the output if both
the outer group and the inner group are eligible for output. the outer group and the inner group are eligible for output.
#### TimeWrapper TimeWrapper
~~~~~~~~~~~
Some modules that output times use TimeWrapper to format these. TimeWrapper is Some modules that output times use TimeWrapper to format these. TimeWrapper is
a mere extension of the standard formatting method. a mere extension of the standard formatting method.
@ -211,55 +226,35 @@ The time format that should be used is specified using the format specifier, i.e
with some_time being 3951 seconds a format string like `{some_time:%h:%m:%s}` with some_time being 3951 seconds a format string like `{some_time:%h:%m:%s}`
would produce `1:5:51` would produce `1:5:51`
* `%h`, `%m` and `%s` are the hours, minutes and seconds without leading zeros * `%h`, `%m` and `%s` are the hours, minutes and seconds without
(i.e. 0 to 59 for minutes and seconds) leading zeros (i.e. 0 to 59 for minutes and seconds)
* `%H`, `%M` and `%S` are padded with a leading zero to two digits, i.e. 00 to 59 * `%H`, `%M` and `%S` are padded with a leading zero to two digits,
* `%l` and `%L` produce hours non-padded and padded but only if hours is not zero. i.e. 00 to 59
If the hours are zero it produces an empty string. * `%l` and `%L` produce hours non-padded and padded but only if hours
is not zero. If the hours are zero it produces an empty string.
* `%%` produces a literal % * `%%` produces a literal %
* `%E` (only valid on beginning of the string) if the time is null, don't format * `%E` (only valid on beginning of the string) if the time is null,
anything but rather produce an empty string. If the time is non-null it is don't format anything but rather produce an empty string. If the
removed from the string. time is non-null it is removed from the string.
* When the module in question also uses formatp, 0 seconds counts as "not known". * When the module in question also uses formatp, 0 seconds counts as
* The formatted time is stripped, i.e. spaces on both ends of the result are removed "not known".
* The formatted time is stripped, i.e. spaces on both ends of the
result are removed
## Modules Modules
-------
System: :System: `clock`_ - `disk`_ - `load`_ - `mem`_
[Clock](#clock) - :Audio: `alsa`_ - `pulseaudio`_
[Free space](#disk) - :Hardware: `battery`_ - `backlight`_ - `temp`_
[System load](#load) - :Network: `network`_ - `wireless`_
[Memory usage](#mem) :Other: `mail`_ - `parcel`_ - `pyload`_ - `weather`_ - `mpd`_ - `text`_
:Advanced: `file`_ - `regex`_ - `runwatch`_
Audio:
[ALSA](#alsa) -
[PulseAudio](#pulseaudio)
Hardware:
[Battery](#battery) -
[Screen brightness](#backlight) -
[CPU temperature (Intel)](#temp)
Network:
[Wired](#network) -
[Wireless](#wireless)
Other:
[Unread mail](#mail) -
[Tracking parcels](#parcel) -
[pyLoad](#pyload) -
[Weather](#weather) -
[Music Player Daemon (MPD)](#mpd) -
[Simple text](#text)
Advanced:
[Rip info from files](#file) -
[Regular expressions](#regex) -
[Run watcher](#runwatch)
!!module_doc!! !!module_doc!!
## Contribute Contribute
----------
To contribute a module, make sure it uses one of the Module classes. Most modules To contribute a module, make sure it uses one of the Module classes. Most modules
use IntervalModule, which just calls a function repeatedly in a specified interval. use IntervalModule, which just calls a function repeatedly in a specified interval.
@ -268,8 +263,3 @@ The output attribute should be set to a dictionary which represents your modules
the protocol is documented [here](http://i3wm.org/docs/i3bar-protocol.html). the protocol is documented [here](http://i3wm.org/docs/i3bar-protocol.html).
**Patches and pull requests are very welcome :-)** **Patches and pull requests are very welcome :-)**
### The README
The README.md file is generated from the README.tpl.md file; only edit the latter
and run `python -m i3pystatus.mkdocs`.

View File

@ -9,13 +9,15 @@ class File(IntervalModule):
Rip information from text files Rip information from text files
components is a dict of pairs of the form: components is a dict of pairs of the form:
::
name => (callable, file) name => (callable, file)
* Where `name` is a valid identifier, which is used in the format string to access * Where `name` is a valid identifier, which is used in the format string to access
the value of that component. the value of that component.
* `callable` is some callable to convert the contents of `file`. A common choice is * `callable` is some callable to convert the contents of `file`. A common choice is
float or int. float or int.
* `file` names a file, relative to `base_path`. * `file` names a file, relative to `base_path`.
transforms is a optional dict of callables taking a single argument (a dictionary containing the values transforms is a optional dict of callables taking a single argument (a dictionary containing the values

View File

@ -22,8 +22,7 @@ class Thunderbird(Backend):
This class listens for dbus signals emitted by This class listens for dbus signals emitted by
the dbus-sender extension for thunderbird. the dbus-sender extension for thunderbird.
Requires Requires python-dbus
* python-dbus
""" """
_unread = set() _unread = set()

View File

@ -9,6 +9,7 @@ class Mem(IntervalModule):
Shows memory load Shows memory load
Available formatters: Available formatters:
* {avail_mem} * {avail_mem}
* {percent_used_mem} * {percent_used_mem}
* {used_mem} * {used_mem}

View File

@ -10,11 +10,12 @@ from .core.imputil import ClassFinder
IGNORE = ("__main__", "mkdocs", "core") IGNORE = ("__main__", "mkdocs", "core")
MODULE_FORMAT = """ MODULE_FORMAT = """
{heading} {name} {name}
{heading}
{doc} {doc}
__Settings:__ Settings:
{settings} {settings}
@ -56,7 +57,7 @@ class Module:
name=self.name, name=self.name,
doc=textwrap.dedent(self.doc), doc=textwrap.dedent(self.doc),
settings=self.format_settings(), settings=self.format_settings(),
heading=self.heading, heading=self.heading * len(self.name),
endstring=self.endstring endstring=self.endstring
) )
@ -83,15 +84,11 @@ class Setting:
if self.required: if self.required:
attrs.append("required") attrs.append("required")
if self.default is not self.sentinel: if self.default is not self.sentinel:
attrs.append("default: `{default}`".format(default=self.default)) attrs.append("default: '{default}'".format(default=self.default))
formatted = "* `{name}` ".format(name=self.name) formatted = ":{name}: {doc}".format(name=self.name, doc=self.doc)
if self.doc or attrs: if attrs:
formatted += "" formatted += " ({attrs})".format(attrs=", ".join(attrs))
if self.doc:
formatted += self.doc
if attrs:
formatted += " ({attrs})".format(attrs=", ".join(attrs))
return formatted return formatted
@ -126,15 +123,15 @@ def get_all(module_path, heading, finder=None, ignore=None):
return sorted(mods, key=lambda module: module.name) return sorted(mods, key=lambda module: module.name)
def generate_doc_for_module(module_path, heading="###", finder=None, ignore=None): def generate_doc_for_module(module_path, heading="+", finder=None, ignore=None):
return "".join(map(str, get_all(module_path, heading, finder, ignore or []))) return "".join(map(str, get_all(module_path, heading, finder, ignore or [])))
with open("README.tpl.md", "r") as template: with open("README.tpl.rst", "r") as template:
tpl = template.read() tpl = template.read()
tpl = tpl.replace( tpl = tpl.replace(
"!!module_doc!!", generate_doc_for_module(i3pystatus.__path__)) "!!module_doc!!", generate_doc_for_module(i3pystatus.__path__))
finder = ClassFinder(baseclass=i3pystatus.mail.Backend) finder = ClassFinder(baseclass=i3pystatus.mail.Backend)
tpl = tpl.replace("!!i3pystatus.mail!!", generate_doc_for_module( tpl = tpl.replace("!!i3pystatus.mail!!", generate_doc_for_module(
i3pystatus.mail.__path__, "###", finder, ["Backend"]).replace("\n", "\n> ")) i3pystatus.mail.__path__, "~", finder, ["Backend"]).replace("\n", "\n"))
with open("README.md", "w") as output: with open("README.rst", "w") as output:
output.write(tpl + "\n") output.write(tpl + "\n")

View File

@ -14,11 +14,12 @@ class MPD(IntervalModule):
""" """
Displays various information from MPD (the music player daemon) Displays various information from MPD (the music player daemon)
Available formatters (uses formatp) Available formatters (uses `formatp`_)
* `{title}` (the title of the current song) * `{title}` (the title of the current song)
* `{album}` (the album of the current song, can be an empty string (e.g. for online streams)) * `{album}` (the album of the current song, can be an empty string (e.g. for online streams))
* `{artist}` (can be empty, too) * `{artist}` (can be empty, too)
* `{song_elapsed}` (Position in the currently playing song, **uses TimeWrapper**, default is `%m:%S`) * `{song_elapsed}` (Position in the currently playing song, uses `TimeWrapper`_, default is `%m:%S`)
* `{song_length}` (Length of the current song, same as song_elapsed) * `{song_length}` (Length of the current song, same as song_elapsed)
* `{pos}` (Position of current song in playlist, one-based) * `{pos}` (Position of current song in playlist, one-based)
* `{len}` (Songs in playlist) * `{len}` (Songs in playlist)

View File

@ -54,6 +54,7 @@ class Network(IntervalModule):
Requires the PyPI package `netifaces-py3`. Requires the PyPI package `netifaces-py3`.
Available formatters: Available formatters:
* `{interface}` same as setting * `{interface}` same as setting
* `{name}` same as setting * `{name}` same as setting
* `{v4}` IPv4 address * `{v4}` IPv4 address
@ -71,6 +72,7 @@ class Network(IntervalModule):
("interface", "Interface to obtain information for"), ("interface", "Interface to obtain information for"),
"format_up", "color_up", "format_up", "color_up",
"format_down", "color_down", "format_down", "color_down",
("detached_down", "If the interface doesn't exist, display it as if it were down"),
"name", "name",
) )
@ -79,24 +81,28 @@ class Network(IntervalModule):
format_down = "{interface}" format_down = "{interface}"
color_up = "#00FF00" color_up = "#00FF00"
color_down = "#FF0000" color_down = "#FF0000"
detached_down = False
def init(self): def init(self):
if self.interface not in netifaces.interfaces(): if self.interface not in netifaces.interfaces() and not self.detached_down:
raise RuntimeError( raise RuntimeError(
"Unknown interface {iface}!".format(iface=self.interface)) "Unknown interface {iface}!".format(iface=self.interface))
self.baseinfo = {
"interface": self.interface,
"name": self.name,
"mac": netifaces.ifaddresses(self.interface)[netifaces.AF_PACKET][0]["addr"],
}
def collect(self): def collect(self):
if self.interface not in netifaces.interfaces() and self.detached_down:
self.format = self.format_down
color = self.color_down
return self.color_down, self.format_down, {"interface": self.interface, "name": self.name}, False
info = netifaces.ifaddresses(self.interface) info = netifaces.ifaddresses(self.interface)
up = netifaces.AF_INET in info or netifaces.AF_INET6 in info up = netifaces.AF_INET in info or netifaces.AF_INET6 in info
fdict = dict( fdict = dict(
zip_longest(["v4", "v4mask", "v4cidr", "v6", "v6mask", "v6cidr"], [], fillvalue="")) zip_longest(["v4", "v4mask", "v4cidr", "v6", "v6mask", "v6cidr"], [], fillvalue=""))
fdict.update(self.baseinfo) fdict.update({
"interface": self.interface,
"name": self.name,
"mac": info[netifaces.AF_PACKET][0]["addr"],
})
if up: if up:
format = self.format_up format = self.format_up
@ -115,7 +121,7 @@ class Network(IntervalModule):
format = self.format_down format = self.format_down
color = self.color_down color = self.color_down
return (color, format, fdict, up) return color, format, fdict, up
def run(self): def run(self):
color, format, fdict, up = self.collect() color, format, fdict, up = self.collect()

View File

@ -9,9 +9,10 @@ class PulseAudio(Module):
Shows volume of default PulseAudio sink (output). Shows volume of default PulseAudio sink (output).
Available formatters: Available formatters:
* `{volume}` volume in percent (0...100) * `{volume}` volume in percent (0...100)
* `{db}` volume in decibels relative to 100 %, i.e. 100 % = 0 dB, 50 % = -18 dB, 0 % = -infinity dB * `{db}` volume in decibels relative to 100 %, i.e. 100 % = 0 dB, 50 % = -18 dB, 0 % = -infinity dB
(the literal value for -infinity is `-`) (the literal value for -infinity is `-`)
* `{muted}` the value of one of the `muted` or `unmuted` settings * `{muted}` the value of one of the `muted` or `unmuted` settings
""" """

View File

@ -15,6 +15,7 @@ class pyLoad(IntervalModule):
Shows pyLoad status Shows pyLoad status
Available formatters: Available formatters:
* `{captcha}` (see captcha_true and captcha_false, which are the values filled in for this formatter) * `{captcha}` (see captcha_true and captcha_false, which are the values filled in for this formatter)
* `{progress}` (average over all running downloads) * `{progress}` (average over all running downloads)
* `{progress_all}` (percentage of completed files/links in queue) * `{progress_all}` (percentage of completed files/links in queue)

View File

@ -9,8 +9,9 @@ class Weather(IntervalModule):
This module gets the weather from weather.com using pywapi module This module gets the weather from weather.com using pywapi module
First, you need to get the code for the location from the www.weather.com First, you need to get the code for the location from the www.weather.com
Available formatters: Available formatters:
{current_temp}
{humidity} * {current_temp}
* {humidity}
Requires pywapi from PyPI. Requires pywapi from PyPI.
""" """
@ -19,7 +20,7 @@ class Weather(IntervalModule):
settings = ( settings = (
"location_code", "location_code",
("units", "*C*elsius or *F*ahrenheit"), ("units", "Celsius (C) or Fahrenheit (F)"),
"format", "format",
) )
required = ("location_code",) required = ("location_code",)

View File

@ -12,7 +12,8 @@ class Wireless(Network):
Requires the PyPI packages `netifaces-py3` and `basiciw`. Requires the PyPI packages `netifaces-py3` and `basiciw`.
This is based on the network module, so all options and formatters are This is based on the network module, so all options and formatters are
the same, except for these additional formatters: the same, except for these additional formatters and that detached_down doesn't work.
* `{essid}` ESSID of currently connected wifi * `{essid}` ESSID of currently connected wifi
* `{freq}` Current frequency * `{freq}` Current frequency
* `{quality}` Link quality in percent * `{quality}` Link quality in percent
@ -37,4 +38,4 @@ class Wireless(Network):
fdict["essid"] = "" fdict["essid"] = ""
fdict["freq"] = fdict["quality"] = 0.0 fdict["freq"] = fdict["quality"] = 0.0
return (color, format, fdict, up) return color, format, fdict, up

View File

@ -3,7 +3,7 @@
from setuptools import setup from setuptools import setup
setup(name="i3pystatus", setup(name="i3pystatus",
version="3.27", version="3.28",
description="Like i3status, this generates status line for i3bar / i3wm", description="Like i3status, this generates status line for i3bar / i3wm",
url="http://github.com/enkore/i3pystatus", url="http://github.com/enkore/i3pystatus",
license="MIT", license="MIT",