mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-01 18:51:04 +02:00
Merge branch 'master' into feat/script-watch
This commit is contained in:
commit
b4db0226cd
24 changed files with 1788 additions and 65 deletions
22
.github/workflows/wiki.yml
vendored
Normal file
22
.github/workflows/wiki.yml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
name: Sync Wiki
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Sync Wiki
|
||||||
|
uses: joeizzard/action-wiki-sync@master
|
||||||
|
with:
|
||||||
|
username: JakeStanger
|
||||||
|
access_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
wiki_folder: docs
|
||||||
|
commit_username: 'Jake Stanger'
|
||||||
|
commit_email: 'mail@jstanger.dev'
|
||||||
|
commit_message: 'sync wiki from main repo'
|
268
docs/Configuration guide.md
Normal file
268
docs/Configuration guide.md
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
By default, you get a single bar at the bottom of all your screens.
|
||||||
|
To change that, you'll unsurprisingly need a config file.
|
||||||
|
|
||||||
|
## 1. Create config file
|
||||||
|
|
||||||
|
The config file lives inside the `ironbar` directory in your XDG_CONFIG_DIR, which is usually `~/.config/ironbar`.
|
||||||
|
|
||||||
|
Ironbar supports a range of configuration formats, so you can pick your favourite:
|
||||||
|
|
||||||
|
- `config.json`
|
||||||
|
- `config.toml`
|
||||||
|
- `config.yaml`
|
||||||
|
- `config.corn` (Experimental, includes variable support for re-using blocks.
|
||||||
|
See [here](https://github.com/jakestanger/corn) for info)
|
||||||
|
|
||||||
|
You can also override the default config path using the `IRONBAR_CONFIG` environment variable.
|
||||||
|
|
||||||
|
## 2. Pick your use-case
|
||||||
|
|
||||||
|
Ironbar gives you a few ways to configure the bar to suit your needs.
|
||||||
|
This allows you to keep your config simple and relatively flat if your use-case is simple,
|
||||||
|
and make it more complex if required.
|
||||||
|
|
||||||
|
### a) I want the same bar across all monitors
|
||||||
|
|
||||||
|
Place the bar config inside the top-level object. This is automatically applied to each of your monitors.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"position": "bottom",
|
||||||
|
"height": 42,
|
||||||
|
"start": [],
|
||||||
|
"center": [],
|
||||||
|
"end": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
position = "bottom"
|
||||||
|
height = 42
|
||||||
|
start = []
|
||||||
|
center = []
|
||||||
|
end = []
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
position: "bottom"
|
||||||
|
height: 42
|
||||||
|
start: [ ]
|
||||||
|
center: [ ]
|
||||||
|
end: [ ]
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
position = "bottom"
|
||||||
|
height = 42
|
||||||
|
start = []
|
||||||
|
center = []
|
||||||
|
end = []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### b) I want my config to differ across one or more monitors
|
||||||
|
|
||||||
|
Create a map/object called `monitors` inside the top-level object.
|
||||||
|
Each of the map's keys should be an output name,
|
||||||
|
and each value should be an object containing the bar config.
|
||||||
|
|
||||||
|
To find your output names, run `wayland-info | grep wl_output -A1`.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"monitors": {
|
||||||
|
"DP-1": {
|
||||||
|
"start": []
|
||||||
|
},
|
||||||
|
"DP-2": {
|
||||||
|
"position": "bottom",
|
||||||
|
"height": 30,
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[monitors]
|
||||||
|
|
||||||
|
[monitors.DP-1]
|
||||||
|
start = []
|
||||||
|
|
||||||
|
[monitors.DP-2]
|
||||||
|
position = "bottom"
|
||||||
|
height = 30
|
||||||
|
start = []
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
monitors:
|
||||||
|
DP-1:
|
||||||
|
start: [ ]
|
||||||
|
DP-2:
|
||||||
|
position: "bottom"
|
||||||
|
height: 30
|
||||||
|
start: [ ]
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
monitors.DP-1.start = []
|
||||||
|
monitors.DP-2 = {
|
||||||
|
position = "bottom"
|
||||||
|
height = 30
|
||||||
|
start = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### c) I want one or more monitors to have multiple bars
|
||||||
|
|
||||||
|
Create a map/object called `monitors` inside the top-level object.
|
||||||
|
Each of the map's keys should be an output name.
|
||||||
|
If you want the screen to have multiple bars, use an array of bar config objects.
|
||||||
|
If you want the screen to have a single bar, use an object.
|
||||||
|
|
||||||
|
To find your output names, run `wayland-info | grep wl_output -A1`.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"monitors": {
|
||||||
|
"DP-1": [
|
||||||
|
{
|
||||||
|
"start": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": "top",
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"DP-2": {
|
||||||
|
"position": "bottom",
|
||||||
|
"height": 30,
|
||||||
|
"start": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[monitors]
|
||||||
|
|
||||||
|
[[monitors.DP-1]]
|
||||||
|
start = []
|
||||||
|
|
||||||
|
[[monitors.DP-2]]
|
||||||
|
position = "top"
|
||||||
|
start = []
|
||||||
|
|
||||||
|
[monitors.DP-2]
|
||||||
|
position = "bottom"
|
||||||
|
height = 30
|
||||||
|
start = []
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
monitors:
|
||||||
|
DP-1:
|
||||||
|
- start: [ ]
|
||||||
|
- position: "top"
|
||||||
|
start: [ ]
|
||||||
|
DP-2:
|
||||||
|
position: "bottom"
|
||||||
|
height: 30
|
||||||
|
start: [ ]
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
monitors.DP-1 = [
|
||||||
|
{ start = [] }
|
||||||
|
{ position = "top" start = [] }
|
||||||
|
]
|
||||||
|
monitors.DP-2 = {
|
||||||
|
position = "bottom"
|
||||||
|
height = 30
|
||||||
|
start = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 3. Write your bar config(s)
|
||||||
|
|
||||||
|
Once you have the basic config structure set up, it's time to actually configure your bar(s).
|
||||||
|
|
||||||
|
The following table describes each of the top-level bar config options.
|
||||||
|
For details on available modules and each of their config options, check the sidebar.
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|-------------------|----------------------------------------|----------|-----------------------------------------------------------------------------------------|
|
||||||
|
| `position` | `top` or `bottom` or `left` or `right` | `bottom` | The bar's position on screen. |
|
||||||
|
| `anchor_to_edges` | `boolean` | `false` | Whether to anchor the bar to the edges of the screen. Setting to false centres the bar. |
|
||||||
|
| `height` | `integer` | `42` | The bar's height in pixels. |
|
||||||
|
| `start` | `Module[]` | `[]` | Array of left or top modules. |
|
||||||
|
| `center` | `Module[]` | `[]` | Array of center modules. |
|
||||||
|
| `end` | `Module[]` | `[]` | Array of right or bottom modules. |
|
||||||
|
|
||||||
|
Check [here](config) for an example config file for a fully configured bar in each format.
|
4
docs/Home.md
Normal file
4
docs/Home.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Welcome to the Ironbar wiki.
|
||||||
|
|
||||||
|
Detail about each module, and their configuration and styling options can be found on the sidebar.
|
||||||
|
You can also find an example configuration and stylesheet there.
|
20
docs/Styling guide.md
Normal file
20
docs/Styling guide.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
Ironbar ships with no styles by default, so will fall back to the default GTK styles.
|
||||||
|
|
||||||
|
To style the bar, create a file at `~/.config/ironbar/style.css`.
|
||||||
|
|
||||||
|
Style changes are hot-loaded so there is no need to reload the bar.
|
||||||
|
|
||||||
|
A reminder: since the bar is GTK-based, it uses GTK's implementation of CSS,
|
||||||
|
which only includes a subset of the full web spec (plus a few non-standard properties).
|
||||||
|
|
||||||
|
The below table describes the selectors provided by the bar itself.
|
||||||
|
Information on styling individual modules can be found on their pages in the sidebar.
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|----------------|-------------------------------------------|
|
||||||
|
| `.background` | Top-level window |
|
||||||
|
| `#bar` | Bar root box |
|
||||||
|
| `#bar #start` | Bar left or top modules container box |
|
||||||
|
| `#bar #center` | Bar center modules container box |
|
||||||
|
| `#bar #end` | Bar right or bottom modules container box |
|
||||||
|
| `.container` | All of the above |
|
176
docs/Sys-Info.md
Normal file
176
docs/Sys-Info.md
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
Displays one or more labels containing system information.
|
||||||
|
|
||||||
|
Separating information across several labels allows for styling each one independently.
|
||||||
|
Pango markup is supported.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `sys-info`
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|--------------------|--------------------|---------|--------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `format` | `string[]` | `null` | Array of strings including formatting tokens. For available tokens see below. |
|
||||||
|
| `interval` | `integer` or `Map` | `5` | Seconds between refreshing. Can be a single value for all data or a map of individual refresh values for different data types. |
|
||||||
|
| `interval.memory` | `integer` | `5` | Seconds between refreshing memory data |
|
||||||
|
| `interval.cpu` | `integer` | `5` | Seconds between refreshing cpu data |
|
||||||
|
| `interval.temps` | `integer` | `5` | Seconds between refreshing temperature data |
|
||||||
|
| `interval.disks` | `integer` | `5` | Seconds between refreshing disk data |
|
||||||
|
| `interval.network` | `integer` | `5` | Seconds between refreshing network data |
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"end": [
|
||||||
|
{
|
||||||
|
"format": [
|
||||||
|
" {cpu-percent}% | {temp-c:k10temp-Tccd1}°C",
|
||||||
|
" {memory-used} / {memory-total} GB ({memory-percent}%)",
|
||||||
|
"| {swap-used} / {swap-total} GB ({swap-percent}%)",
|
||||||
|
" {disk-used:/} / {disk-total:/} GB ({disk-percent:/}%)",
|
||||||
|
"李 {net-down:enp39s0} / {net-up:enp39s0} Mbps",
|
||||||
|
"猪 {load-average:1} | {load-average:5} | {load-average:15}",
|
||||||
|
" {uptime}"
|
||||||
|
],
|
||||||
|
"interval": {
|
||||||
|
"cpu": 1,
|
||||||
|
"disks": 300,
|
||||||
|
"memory": 30,
|
||||||
|
"networks": 3,
|
||||||
|
"temps": 5
|
||||||
|
},
|
||||||
|
"type": "sys-info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[end]]
|
||||||
|
type = 'sys-info'
|
||||||
|
format = [
|
||||||
|
' {cpu-percent}% | {temp-c:k10temp-Tccd1}°C',
|
||||||
|
' {memory-used} / {memory-total} GB ({memory-percent}%)',
|
||||||
|
'| {swap-used} / {swap-total} GB ({swap-percent}%)',
|
||||||
|
' {disk-used:/} / {disk-total:/} GB ({disk-percent:/}%)',
|
||||||
|
'李 {net-down:enp39s0} / {net-up:enp39s0} Mbps',
|
||||||
|
'猪 {load-average:1} | {load-average:5} | {load-average:15}',
|
||||||
|
' {uptime}',
|
||||||
|
]
|
||||||
|
|
||||||
|
[end.interval]
|
||||||
|
cpu = 1
|
||||||
|
disks = 300
|
||||||
|
memory = 30
|
||||||
|
networks = 3
|
||||||
|
temps = 5
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
end:
|
||||||
|
- format:
|
||||||
|
- {cpu-percent}% | {temp-c:k10temp-Tccd1}°C
|
||||||
|
- {memory-used} / {memory-total} GB ({memory-percent}%)
|
||||||
|
- '| {swap-used} / {swap-total} GB ({swap-percent}%)'
|
||||||
|
- {disk-used:/} / {disk-total:/} GB ({disk-percent:/}%)
|
||||||
|
- 李 {net-down:enp39s0} / {net-up:enp39s0} Mbps
|
||||||
|
- 猪 {load-average:1} | {load-average:5} | {load-average:15}
|
||||||
|
- {uptime}
|
||||||
|
interval:
|
||||||
|
cpu: 1
|
||||||
|
disks: 300
|
||||||
|
memory: 30
|
||||||
|
networks: 3
|
||||||
|
temps: 5
|
||||||
|
type: sys-info
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
{
|
||||||
|
end = [
|
||||||
|
{
|
||||||
|
type = "sys-info"
|
||||||
|
|
||||||
|
interval.memory = 30
|
||||||
|
interval.cpu = 1
|
||||||
|
interval.temps = 5
|
||||||
|
interval.disks = 300
|
||||||
|
interval.networks = 3
|
||||||
|
|
||||||
|
format = [
|
||||||
|
" {cpu-percent}% | {temp-c:k10temp-Tccd1}°C"
|
||||||
|
" {memory-used} / {memory-total} GB ({memory-percent}%)"
|
||||||
|
"| {swap-used} / {swap-total} GB ({swap-percent}%)"
|
||||||
|
" {disk-used:/} / {disk-total:/} GB ({disk-percent:/}%)"
|
||||||
|
"李 {net-down:enp39s0} / {net-up:enp39s0} Mbps"
|
||||||
|
"猪 {load-average:1} | {load-average:5} | {load-average:15}"
|
||||||
|
" {uptime}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### Formatting Tokens
|
||||||
|
|
||||||
|
The following tokens can be used in the `format` configuration option:
|
||||||
|
|
||||||
|
| Token | Description |
|
||||||
|
|--------------------------|------------------------------------------------------------------------------------|
|
||||||
|
| **CPU** | |
|
||||||
|
| `{cpu-percent}` | Total CPU utilisation percentage |
|
||||||
|
| **Memory** | |
|
||||||
|
| `{memory-free}` | Memory free in GB. |
|
||||||
|
| `{memory-used}` | Memory used in GB. |
|
||||||
|
| `{memory-total}` | Memory total in GB. |
|
||||||
|
| `{memory-percent}` | Memory utilisation percentage. |
|
||||||
|
| `{swap-free}` | Swap free in GB. |
|
||||||
|
| `{swap-used}` | Swap used in GB. |
|
||||||
|
| `{swap-total}` | Swap total in GB. |
|
||||||
|
| `{swap-percent}` | Swap utilisation percentage. |
|
||||||
|
| **Temperature** | |
|
||||||
|
| `{temp-c:[sensor]}` | Temperature in degrees C. Replace `[sensor]` with the sensor label. |
|
||||||
|
| `{temp-f:[sensor]}` | Temperature in degrees F. Replace `[sensor]` with the sensor label. |
|
||||||
|
| **Disk** | |
|
||||||
|
| `{disk-free:[mount]}` | Disk free space in GB. Replace `[mount]` with the disk mountpoint. |
|
||||||
|
| `{disk-used:[mount]}` | Disk used space in GB. Replace `[mount]` with the disk mountpoint. |
|
||||||
|
| `{disk-total:[mount]}` | Disk total space in GB. Replace `[mount]` with the disk mountpoint. |
|
||||||
|
| `{disk-percent:[mount]}` | Disk utilisation percentage. Replace `[mount]` with the disk mountpoint. |
|
||||||
|
| **Network** | |
|
||||||
|
| `{net-down:[adapter]}` | Average network download speed in Mbps. Replace `[adapter]` with the adapter name. |
|
||||||
|
| `{net-up:[adapter]}` | Average network upload speed in Mbps. Replace `[adapter]` with the adapter name. |
|
||||||
|
| **System** | |
|
||||||
|
| `{load-average:1}` | 1-minute load average. |
|
||||||
|
| `{load-average:5}` | 5-minute load average. |
|
||||||
|
| `{load-average:15}` | 15-minute load average. |
|
||||||
|
| `{uptime}` | System uptime formatted as `HH:mm`. |
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|------------------|------------------------------|
|
||||||
|
| `#sysinfo` | Sysinfo widget box |
|
||||||
|
| `#sysinfo #item` | Individual information label |
|
21
docs/_Sidebar.md
Normal file
21
docs/_Sidebar.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Guides
|
||||||
|
|
||||||
|
- [Configuration guide](configuration-guide)
|
||||||
|
- [Styling guide](styling-guide)
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
- [Config](config)
|
||||||
|
- [Stylesheet](stylesheet)
|
||||||
|
|
||||||
|
# Modules
|
||||||
|
|
||||||
|
- [Clock](clock)
|
||||||
|
- [Custom](custom)
|
||||||
|
- [Focused](focused)
|
||||||
|
- [Launcher](launcher)
|
||||||
|
- [MPD](mpd)
|
||||||
|
- [Script](script)
|
||||||
|
- [Sys-info](sys-info)
|
||||||
|
- [Tray](tray)
|
||||||
|
- [Workspaces](workspaces)
|
202
docs/examples/Config.md
Normal file
202
docs/examples/Config.md
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
The below config shows a module of each type being used.
|
||||||
|
|
||||||
|
The Corn format makes heavy use of variables
|
||||||
|
to show how module configs can be easily referenced to improve readability
|
||||||
|
and reduce config length when using multiple bars.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"start": [
|
||||||
|
{
|
||||||
|
"all_monitors": false,
|
||||||
|
"name_map": {
|
||||||
|
"1": "ﭮ",
|
||||||
|
"2": "",
|
||||||
|
"3": "",
|
||||||
|
"Code": "",
|
||||||
|
"Games": ""
|
||||||
|
},
|
||||||
|
"type": "workspaces"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"favorites": [
|
||||||
|
"firefox",
|
||||||
|
"discord",
|
||||||
|
"Steam"
|
||||||
|
],
|
||||||
|
"icon_theme": "Paper",
|
||||||
|
"show_icons": true,
|
||||||
|
"show_names": false,
|
||||||
|
"type": "launcher"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end": [
|
||||||
|
{
|
||||||
|
"music_dir": "/home/jake/Music",
|
||||||
|
"type": "mpd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"host": "chloe:6600",
|
||||||
|
"type": "mpd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/jake/bin/phone-battery",
|
||||||
|
"type": "script"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": [
|
||||||
|
"{cpu-percent}% ",
|
||||||
|
"{memory-percent}% "
|
||||||
|
],
|
||||||
|
"type": "sys-info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "clock"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[start]]
|
||||||
|
all_monitors = false
|
||||||
|
type = 'workspaces'
|
||||||
|
|
||||||
|
[start.name_map]
|
||||||
|
1 = 'ﭮ'
|
||||||
|
2 = ''
|
||||||
|
3 = ''
|
||||||
|
Code = ''
|
||||||
|
Games = ''
|
||||||
|
|
||||||
|
[[start]]
|
||||||
|
icon_theme = 'Paper'
|
||||||
|
show_icons = true
|
||||||
|
show_names = false
|
||||||
|
type = 'launcher'
|
||||||
|
favorites = [
|
||||||
|
'firefox',
|
||||||
|
'discord',
|
||||||
|
'Steam',
|
||||||
|
]
|
||||||
|
|
||||||
|
[[end]]
|
||||||
|
music_dir = '/home/jake/Music'
|
||||||
|
type = 'mpd'
|
||||||
|
|
||||||
|
[[end]]
|
||||||
|
host = 'chloe:6600'
|
||||||
|
type = 'mpd'
|
||||||
|
|
||||||
|
[[end]]
|
||||||
|
path = '/home/jake/bin/phone-battery'
|
||||||
|
type = 'script'
|
||||||
|
|
||||||
|
[[end]]
|
||||||
|
type = 'sys-info'
|
||||||
|
format = [
|
||||||
|
'{cpu-percent}% ',
|
||||||
|
'{memory-percent}% ',
|
||||||
|
]
|
||||||
|
|
||||||
|
[[end]]
|
||||||
|
type = 'clock'
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
start:
|
||||||
|
- all_monitors: false
|
||||||
|
name_map:
|
||||||
|
"1": ﭮ
|
||||||
|
"2":
|
||||||
|
"3":
|
||||||
|
Code:
|
||||||
|
Games:
|
||||||
|
type: workspaces
|
||||||
|
- favorites:
|
||||||
|
- firefox
|
||||||
|
- discord
|
||||||
|
- Steam
|
||||||
|
icon_theme: Paper
|
||||||
|
show_icons: true
|
||||||
|
show_names: false
|
||||||
|
type: launcher
|
||||||
|
end:
|
||||||
|
- music_dir: /home/jake/Music
|
||||||
|
type: mpd
|
||||||
|
- host: "chloe:6600"
|
||||||
|
type: mpd
|
||||||
|
- path: /home/jake/bin/phone-battery
|
||||||
|
type: script
|
||||||
|
- format:
|
||||||
|
- "{cpu-percent}% "
|
||||||
|
- "{memory-percent}% "
|
||||||
|
type: sys-info
|
||||||
|
- type: clock
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
let {
|
||||||
|
$workspaces = {
|
||||||
|
type = "workspaces"
|
||||||
|
all_monitors = false
|
||||||
|
name_map = {
|
||||||
|
1 = "ﭮ"
|
||||||
|
2 = ""
|
||||||
|
3 = ""
|
||||||
|
Games = ""
|
||||||
|
Code = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$launcher = {
|
||||||
|
type = "launcher"
|
||||||
|
favorites = ["firefox" "discord" "Steam"]
|
||||||
|
show_names = false
|
||||||
|
show_icons = true
|
||||||
|
icon_theme = "Paper"
|
||||||
|
}
|
||||||
|
|
||||||
|
$mpd_local = { type = "mpd" music_dir = "/home/jake/Music" }
|
||||||
|
$mpd_server = { type = "mpd" host = "chloe:6600" }
|
||||||
|
|
||||||
|
$sys_info = {
|
||||||
|
type = "sys-info"
|
||||||
|
format = ["{cpu-percent}% " "{memory-percent}% "]
|
||||||
|
}
|
||||||
|
|
||||||
|
$tray = { type = "tray" }
|
||||||
|
$clock = { type = "clock" }
|
||||||
|
|
||||||
|
$phone_battery = {
|
||||||
|
type = "script"
|
||||||
|
path = "/home/jake/bin/phone-battery"
|
||||||
|
}
|
||||||
|
|
||||||
|
$start = [ $workspaces $launcher ]
|
||||||
|
$end = [ $mpd_local $mpd_server $phone_battery $sys_info $clock ]
|
||||||
|
}
|
||||||
|
in {
|
||||||
|
start = $start
|
||||||
|
end = $end
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
142
docs/examples/Stylesheet.md
Normal file
142
docs/examples/Stylesheet.md
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
The below example is a full stylesheet for all modules:
|
||||||
|
|
||||||
|
```css
|
||||||
|
* {
|
||||||
|
/* a nerd font is required to be installed for icons */
|
||||||
|
font-family: Noto Sans Nerd Font, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bar {
|
||||||
|
border-top: 1px solid #424242;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container#end > * + * {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
border: 1px solid #424242;
|
||||||
|
}
|
||||||
|
|
||||||
|
#workspaces .item {
|
||||||
|
color: white;
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#workspaces .item.focused {
|
||||||
|
box-shadow: inset 0 -3px;
|
||||||
|
background-color: #1c1c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#workspaces *:not(.focused):hover {
|
||||||
|
box-shadow: inset 0 -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#launcher .item {
|
||||||
|
border-radius: 0;
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#launcher .item:not(.focused):hover {
|
||||||
|
background-color: #1c1c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#launcher .open {
|
||||||
|
border-bottom: 2px solid #6699cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#launcher .focused {
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
border-bottom: 4px solid #6699cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#launcher .urgent {
|
||||||
|
color: white;
|
||||||
|
background-color: #8f0a0a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#script {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sysinfo {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tray .item {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mpd {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-mpd {
|
||||||
|
color: white;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-mpd #album-art {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-mpd #title .icon, #popup-mpd #title .label {
|
||||||
|
font-size: 1.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-mpd #controls * {
|
||||||
|
border-radius: 0;
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-mpd #controls *:disabled {
|
||||||
|
color: #424242;
|
||||||
|
}
|
||||||
|
|
||||||
|
#clock {
|
||||||
|
color: white;
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-clock {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-clock #calendar-clock {
|
||||||
|
color: white;
|
||||||
|
font-size: 2.5em;
|
||||||
|
padding-bottom: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-clock #calendar {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-clock #calendar .header {
|
||||||
|
padding-top: 1em;
|
||||||
|
border-top: 1px solid #424242;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-clock #calendar:selected {
|
||||||
|
background-color: #6699cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#focused {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
```
|
77
docs/modules/Clock.md
Normal file
77
docs/modules/Clock.md
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
Displays the current date and time.
|
||||||
|
Clicking on the widget opens a popup with the time and a calendar.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `clock`
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|----------|--------|------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `format` | `string` | `%d/%m/%Y %H:%M` | Date/time format string. Detail on available tokens can be found here: <https://docs.rs/chrono/latest/chrono/format/strftime/index.html> |
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"end": [
|
||||||
|
{
|
||||||
|
"type": "clock",
|
||||||
|
"format": "%d/%m/%Y %H:%M"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[end]]
|
||||||
|
type = "clock"
|
||||||
|
format = "%d/%m/%Y %H:%M"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
end:
|
||||||
|
- type: "clock"
|
||||||
|
format: "%d/%m/%Y %H:%M"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
{
|
||||||
|
end = [
|
||||||
|
{
|
||||||
|
type = "clock"
|
||||||
|
format = "%d/%m/%Y %H:%M"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|-------------------------------|------------------------------------------------------------------------------------|
|
||||||
|
| `#clock` | Clock widget button |
|
||||||
|
| `#popup-clock` | Clock popup box |
|
||||||
|
| `#popup-clock #calendar-clock` | Clock inside the popup |
|
||||||
|
| `#popup-clock #calendar` | Calendar widget inside the popup. GTK provides some OOTB styling options for this. |
|
237
docs/modules/Custom.md
Normal file
237
docs/modules/Custom.md
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
Allows you to compose custom modules consisting of multiple widgets, including popups.
|
||||||
|
Buttons can interact with the bar or execute commands on click.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `custom`
|
||||||
|
|
||||||
|
This module can be quite fiddly to configure as you effectively have to build a tree of widgets by hand.
|
||||||
|
It is well worth looking at the examples.
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|---------|------------|---------|--------------------------------------|
|
||||||
|
| `class` | `string` | `null` | Container class name. |
|
||||||
|
| `bar` | `Widget[]` | `null` | List of widgets to add to the bar. |
|
||||||
|
| `popup` | `Widget[]` | `[]` | List of widgets to add to the popup. |
|
||||||
|
|
||||||
|
### `Widget`
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|---------------|------------------------------|--------------|---------------------------------------------------------------------------|
|
||||||
|
| `widget_type` | `box` or `label` or `button` | `null` | Type of GTK widget to create. |
|
||||||
|
| `name` | `string` | `null` | Widget name. |
|
||||||
|
| `class` | `string` | `null` | Widget class name. |
|
||||||
|
| `label` | `string` | `null` | [`label` and `button`] Widget text label. Pango markup supported. |
|
||||||
|
| `exec` | `string` | `null` | [`button`] Command to execute. More on this [below](#commands). |
|
||||||
|
| `orientation` | `horizontal` or `vertical` | `horizontal` | [`box`] Whether child widgets should be horizontally or vertically added. |
|
||||||
|
| `widgets` | `Widget[]` | `[]` | [`box`] List of widgets to add to this box. |
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
Buttons can execute commands that interact with the bar,
|
||||||
|
as well as any arbitrary shell command.
|
||||||
|
|
||||||
|
To execute shell commands, prefix them with an `!`.
|
||||||
|
For example, if you want to run `~/.local/bin/my-script.sh` on click,
|
||||||
|
you'd set `exec` to `!~/.local/bin/my-script.sh`.
|
||||||
|
|
||||||
|
The following bar commands are supported:
|
||||||
|
|
||||||
|
- `popup:toggle`
|
||||||
|
- `popup:open`
|
||||||
|
- `popup:close`
|
||||||
|
|
||||||
|
XML is arguably better-suited and easier to read for this sort of markup,
|
||||||
|
but currently not supported.
|
||||||
|
Nonetheless, it may be worth comparing the examples to the below equivalent
|
||||||
|
to help get your head around what's going on:
|
||||||
|
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<custom class="power-menu">
|
||||||
|
<bar>
|
||||||
|
<button name="power-btn" label="" exec="popup:toggle"/>
|
||||||
|
</bar>
|
||||||
|
<popup>
|
||||||
|
<box orientation="vertical">
|
||||||
|
<label name="header" label="Power menu" />
|
||||||
|
<box>
|
||||||
|
<button class="power-btn" label="" exec="!shutdown now" />
|
||||||
|
<button class="power-btn" label="" exec="!reboot" />
|
||||||
|
</box>
|
||||||
|
</box>
|
||||||
|
</popup>
|
||||||
|
</custom>
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"end": [
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"bar": [
|
||||||
|
{
|
||||||
|
"exec": "popup:toggle",
|
||||||
|
"label": "",
|
||||||
|
"name": "power-btn",
|
||||||
|
"type": "button"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"class": "power-menu",
|
||||||
|
"popup": [
|
||||||
|
{
|
||||||
|
"orientation": "vertical",
|
||||||
|
"type": "box",
|
||||||
|
"widgets": [
|
||||||
|
{
|
||||||
|
"label": "Power menu",
|
||||||
|
"name": "header",
|
||||||
|
"type": "label"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "box",
|
||||||
|
"widgets": [
|
||||||
|
{
|
||||||
|
"class": "power-btn",
|
||||||
|
"exec": "!shutdown now",
|
||||||
|
"label": "<span font-size='40pt'></span>",
|
||||||
|
"type": "button"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "power-btn",
|
||||||
|
"exec": "!reboot",
|
||||||
|
"label": "<span font-size='40pt'></span>",
|
||||||
|
"type": "button"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[end]]
|
||||||
|
class = 'power-menu'
|
||||||
|
type = 'custom'
|
||||||
|
|
||||||
|
[[end.bar]]
|
||||||
|
exec = 'popup:toggle'
|
||||||
|
label = ''
|
||||||
|
name = 'power-btn'
|
||||||
|
type = 'button'
|
||||||
|
|
||||||
|
[[end.popup]]
|
||||||
|
orientation = 'vertical'
|
||||||
|
type = 'box'
|
||||||
|
|
||||||
|
[[end.popup.widgets]]
|
||||||
|
label = 'Power menu'
|
||||||
|
name = 'header'
|
||||||
|
type = 'label'
|
||||||
|
|
||||||
|
[[end.popup.widgets]]
|
||||||
|
type = 'box'
|
||||||
|
|
||||||
|
[[end.popup.widgets.widgets]]
|
||||||
|
class = 'power-btn'
|
||||||
|
exec = '!shutdown now'
|
||||||
|
label = '''<span font-size='40pt'></span>'''
|
||||||
|
type = 'button'
|
||||||
|
|
||||||
|
[[end.popup.widgets.widgets]]
|
||||||
|
class = 'power-btn'
|
||||||
|
exec = '!reboot'
|
||||||
|
label = '''<span font-size='40pt'></span>'''
|
||||||
|
type = 'button'
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
end:
|
||||||
|
- type: custom
|
||||||
|
bar:
|
||||||
|
- exec: popup:toggle
|
||||||
|
label:
|
||||||
|
name: power-btn
|
||||||
|
type: button
|
||||||
|
class: power-menu
|
||||||
|
popup:
|
||||||
|
- orientation: vertical
|
||||||
|
type: box
|
||||||
|
widgets:
|
||||||
|
- label: Power menu
|
||||||
|
name: header
|
||||||
|
type: label
|
||||||
|
- type: box
|
||||||
|
widgets:
|
||||||
|
- class: power-btn
|
||||||
|
exec: '!shutdown now'
|
||||||
|
label: <span font-size='40pt'></span>
|
||||||
|
type: button
|
||||||
|
- class: power-btn
|
||||||
|
exec: '!reboot'
|
||||||
|
label: <span font-size='40pt'></span>
|
||||||
|
type: button
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
let {
|
||||||
|
$power_menu = {
|
||||||
|
type = "custom"
|
||||||
|
class = "power-menu"
|
||||||
|
|
||||||
|
bar = [ { type = "button" name="power-btn" label = "" exec = "popup:toggle" } ]
|
||||||
|
|
||||||
|
popup = [ {
|
||||||
|
type = "box"
|
||||||
|
orientation = "vertical"
|
||||||
|
widgets = [
|
||||||
|
{ type = "label" name = "header" label = "Power menu" }
|
||||||
|
{
|
||||||
|
type = "box"
|
||||||
|
widgets = [
|
||||||
|
{ type = "button" class="power-btn" label = "<span font-size='40pt'></span>" exec = "!shutdown now" }
|
||||||
|
{ type = "button" class="power-btn" label = "<span font-size='40pt'></span>" exec = "!reboot" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
} in {
|
||||||
|
end = [ $power_menu ]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
Since the widgets are all custom, you can target them using `#name` and `.class`.
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|-----------|-------------------------|
|
||||||
|
| `#custom` | Custom widget container |
|
90
docs/modules/Focused.md
Normal file
90
docs/modules/Focused.md
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
Displays the title and/or icon of the currently focused window.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `focused`
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|--------------|-----------|---------|---------------------------------|
|
||||||
|
| `show_icon` | `boolean` | `true` | Whether to show the app's icon |
|
||||||
|
| `show_title` | `boolean` | `true` | Whether to show the app's title |
|
||||||
|
| `icon_size` | `integer` | `32` | Size of icon in pixels |
|
||||||
|
| `icon_theme` | `string` | `null` | GTK icon theme to use |
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"end": [
|
||||||
|
{
|
||||||
|
"type": "focused",
|
||||||
|
"show_icon": true,
|
||||||
|
"show_title": true,
|
||||||
|
"icon_size": 32,
|
||||||
|
"icon_theme": "Paper"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[end]]
|
||||||
|
type = "focused"
|
||||||
|
show_icon = true
|
||||||
|
show_title = true
|
||||||
|
icon_size = 32
|
||||||
|
icon_theme = "Paper"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
end:
|
||||||
|
- type: "focused"
|
||||||
|
show_icon: true
|
||||||
|
show_title: true
|
||||||
|
icon_size: 32
|
||||||
|
icon_theme: "Paper"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
{
|
||||||
|
end = [
|
||||||
|
{
|
||||||
|
type = "focused"
|
||||||
|
show_icon = true
|
||||||
|
show_title = true
|
||||||
|
icon_size = 32
|
||||||
|
icon_theme = "Paper"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|--------------------------|--------------------|
|
||||||
|
| `#focused` | Focused widget box |
|
||||||
|
| `#focused #icon` | App icon |
|
||||||
|
| `#focused #label` | App name |
|
103
docs/modules/Launcher.md
Normal file
103
docs/modules/Launcher.md
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
Windows-style taskbar that displays running windows, grouped by program.
|
||||||
|
Hovering over a program with multiple windows open shows a popup with each window.
|
||||||
|
Clicking an icon/popup item focuses or launches the program.
|
||||||
|
Optionally displays a launchable set of favourites.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `launcher`
|
||||||
|
|
||||||
|
| | Type | Default | Description |
|
||||||
|
|--------------|------------|---------|-----------------------------------------------------------------------------------------------------|
|
||||||
|
| `favorites` | `string[]` | `[]` | List of app IDs (or classes) to always show at the start of the launcher |
|
||||||
|
| `show_names` | `boolean` | `false` | Whether to show app names on the button label. Names will still show on tooltips when set to false. |
|
||||||
|
| `show_icons` | `boolean` | `true` | Whether to show app icons on the button. |
|
||||||
|
| `icon_theme` | `string` | `null` | GTK icon theme to use. |
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"start": [
|
||||||
|
{
|
||||||
|
"type": "launcher",
|
||||||
|
"favourites": [
|
||||||
|
"firefox",
|
||||||
|
"discord"
|
||||||
|
],
|
||||||
|
"show_names": false,
|
||||||
|
"show_icons": true,
|
||||||
|
"icon_theme": "Paper"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[start]]
|
||||||
|
type = "launcher"
|
||||||
|
favorites = ["firefox", "discord"]
|
||||||
|
show_names = false
|
||||||
|
show_icons = true
|
||||||
|
icon_theme = "Paper"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
start:
|
||||||
|
- type: "launcher"
|
||||||
|
favorites:
|
||||||
|
- firefox
|
||||||
|
- discord
|
||||||
|
show_names: false
|
||||||
|
show_icons: true
|
||||||
|
icon_theme: "Paper"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
{
|
||||||
|
start = [
|
||||||
|
{
|
||||||
|
type = "launcher"
|
||||||
|
favorites = ["firefox" "discord"]
|
||||||
|
show_names = false
|
||||||
|
show_icons = true
|
||||||
|
icon_theme = "Paper"
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|-------------------------------|--------------------------|
|
||||||
|
| `#launcher` | Launcher widget box |
|
||||||
|
| `#launcher .item` | App button |
|
||||||
|
| `#launcher .item.open` | App button (open app) |
|
||||||
|
| `#launcher .item.focused` | App button (focused app) |
|
||||||
|
| `#launcher .item.urgent` | App button (urgent app) |
|
||||||
|
| `#launcher-popup` | Popup container |
|
||||||
|
| `#launcher-popup .popup-item` | Window button in popup |
|
131
docs/modules/MPD.md
Normal file
131
docs/modules/MPD.md
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
Displays currently playing song from MPD.
|
||||||
|
Clicking on the widget opens a popout displaying info about the current song, album art
|
||||||
|
and playback controls.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `mpd`
|
||||||
|
|
||||||
|
| | Type | Default | Description |
|
||||||
|
|----------------|----------|-----------------------------|-----------------------------------------------------------------------|
|
||||||
|
| `host` | `string` | `localhost:6600` | TCP or Unix socket for the MPD server. |
|
||||||
|
| `format` | `string` | `{icon} {title} / {artist}` | Format string for the widget. More info below. |
|
||||||
|
| `icons.play` | `string` | `` | Icon to show when playing. |
|
||||||
|
| `icons.pause` | `string` | `` | Icon to show when paused. |
|
||||||
|
| `icons.volume` | `string` | `墳` | Icon to show under popup volume slider. |
|
||||||
|
| `music_dir` | `string` | `$HOME/Music` | Path to MPD server's music directory on disc. Required for album art. |
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"start": [
|
||||||
|
{
|
||||||
|
"type": "mpd",
|
||||||
|
"format": "{icon} {title} / {artist}",
|
||||||
|
"icons": {
|
||||||
|
"play": "",
|
||||||
|
"pause": ""
|
||||||
|
},
|
||||||
|
"music_dir": "/home/jake/Music"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[start]]
|
||||||
|
type = "mpd"
|
||||||
|
format = "{icon} {title} / {artist}"
|
||||||
|
music_dir = "/home/jake/Music"
|
||||||
|
|
||||||
|
[[start.icons]]
|
||||||
|
play = ""
|
||||||
|
pause = ""
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
start:
|
||||||
|
- type: "mpd"
|
||||||
|
format: "{icon} {title} / {artist}"
|
||||||
|
icons:
|
||||||
|
play: ""
|
||||||
|
pause: ""
|
||||||
|
music_dir: "/home/jake/Music"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
{
|
||||||
|
start = [
|
||||||
|
{
|
||||||
|
type = "mpd"
|
||||||
|
format = "{icon} {title} / {artist}"
|
||||||
|
icons.play = ""
|
||||||
|
icons.pause = ""
|
||||||
|
music_dir = "/home/jake/Music"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### Formatting Tokens
|
||||||
|
|
||||||
|
The following tokens can be used in the `format` config option,
|
||||||
|
and will be replaced with values from the currently playing track:
|
||||||
|
|
||||||
|
| Token | Description |
|
||||||
|
|--------------|--------------------------------------|
|
||||||
|
| `{icon}` | Either `icons.play` or `icons.pause` |
|
||||||
|
| `{title}` | Title |
|
||||||
|
| `{album}` | Album name |
|
||||||
|
| `{artist}` | Artist name |
|
||||||
|
| `{date}` | Release date |
|
||||||
|
| `{track}` | Track number |
|
||||||
|
| `{disc}` | Disc number |
|
||||||
|
| `{genre}` | Genre |
|
||||||
|
| `{duration}` | Duration in `mm:ss` |
|
||||||
|
| `{elapsed}` | Time elapsed in `mm:ss` |
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|----------------------------------------|------------------------------------------|
|
||||||
|
| `#mpd` | Tray widget button |
|
||||||
|
| `#popup-mpd` | Popup box |
|
||||||
|
| `#popup-mpd #album-art` | Album art image inside popup box |
|
||||||
|
| `#popup-mpd #title` | Track title container inside popup box |
|
||||||
|
| `#popup-mpd #title .icon` | Track title icon label inside popup box |
|
||||||
|
| `#popup-mpd #title .label` | Track title label inside popup box |
|
||||||
|
| `#popup-mpd #album` | Track album container inside popup box |
|
||||||
|
| `#popup-mpd #album .icon` | Track album icon label inside popup box |
|
||||||
|
| `#popup-mpd #album .label` | Track album label inside popup box |
|
||||||
|
| `#popup-mpd #artist` | Track artist container inside popup box |
|
||||||
|
| `#popup-mpd #artist .icon` | Track artist icon label inside popup box |
|
||||||
|
| `#popup-mpd #artist .label` | Track artist label inside popup box |
|
||||||
|
| `#popup-mpd #controls` | Controls container inside popup box |
|
||||||
|
| `#popup-mpd #controls #btn-prev` | Previous button inside popup box |
|
||||||
|
| `#popup-mpd #controls #btn-play-pause` | Play/pause button inside popup box |
|
||||||
|
| `#popup-mpd #controls #btn-next` | Next button inside popup box |
|
||||||
|
| `#popup-mpd #volume` | Volume container inside popup box |
|
||||||
|
| `#popup-mpd #volume #slider` | Volume slider popup box |
|
||||||
|
| `#popup-mpd #volume .icon` | Volume icon label inside popup box |
|
76
docs/modules/Script.md
Normal file
76
docs/modules/Script.md
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
Executes a script and shows the result of `stdout` on a label.
|
||||||
|
Pango markup is supported.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `script`
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|-----------|----------|---------|---------------------------------------------------------|
|
||||||
|
| `path` | `string` | `null` | Path to the script on disk |
|
||||||
|
| `interval` | `number` | `5000` | Number of milliseconds to wait between executing script |
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"end": [
|
||||||
|
{
|
||||||
|
"type": "script",
|
||||||
|
"path": "/home/jake/.local/bin/phone-battery",
|
||||||
|
"interval": 5000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[end]]
|
||||||
|
type = "script"
|
||||||
|
path = "/home/jake/.local/bin/phone-battery"
|
||||||
|
interval = 5000
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
end:
|
||||||
|
- type: "script"
|
||||||
|
path: "/home/jake/.local/bin/phone-battery"
|
||||||
|
interval : 5000
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
{
|
||||||
|
end = [
|
||||||
|
{
|
||||||
|
type = "script"
|
||||||
|
path = "/home/jake/.local/bin/phone-battery"
|
||||||
|
interval = 5000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|---------------|---------------------|
|
||||||
|
| `#script` | Script widget label |
|
64
docs/modules/Tray.md
Normal file
64
docs/modules/Tray.md
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
Displays a fully interactive icon tray using the KDE `libappindicator` protocol.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `tray`
|
||||||
|
|
||||||
|
***This module provides no configuration options.***
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"end": [
|
||||||
|
{
|
||||||
|
"type": "tray"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[end]]
|
||||||
|
type = "tray"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
end:
|
||||||
|
- type: "tray"
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
{
|
||||||
|
end = [
|
||||||
|
{ type = "tray" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|---------------|------------------|
|
||||||
|
| `#tray` | Tray widget box |
|
||||||
|
| `#tray .item` | Tray icon button |
|
94
docs/modules/Workspaces.md
Normal file
94
docs/modules/Workspaces.md
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
> ⚠ **This module is currently only supported on Sway**
|
||||||
|
|
||||||
|
Shows all current Sway workspaces. Clicking a workspace changes focus to it.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
> Type: `workspaces`
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|----------------|-----------------------|---------|----------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `name_map` | `Map<string, string>` | `{}` | A map of actual workspace names to their display labels. Workspaces use their actual name if not present in the map. |
|
||||||
|
| `all_monitors` | `boolean` | `false` | Whether to display workspaces from all monitors. When `false`, only shows workspaces on the current monitor. |
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>JSON</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"end": [
|
||||||
|
{
|
||||||
|
"type": "workspaces",
|
||||||
|
"name_map": {
|
||||||
|
"1": "",
|
||||||
|
"2": "",
|
||||||
|
"3": ""
|
||||||
|
},
|
||||||
|
"all_monitors": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TOML</summary>
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[end]]
|
||||||
|
type = "workspaces"
|
||||||
|
all_monitors = false
|
||||||
|
|
||||||
|
[[end.name_map]]
|
||||||
|
1 = ""
|
||||||
|
2 = ""
|
||||||
|
3 = ""
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>YAML</summary>
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
end:
|
||||||
|
- type: "workspaces"
|
||||||
|
name_map:
|
||||||
|
1: ""
|
||||||
|
2: ""
|
||||||
|
3: ""
|
||||||
|
all_monitors: false
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Corn</summary>
|
||||||
|
|
||||||
|
```corn
|
||||||
|
{
|
||||||
|
end = [
|
||||||
|
{
|
||||||
|
type = "workspaces",
|
||||||
|
name_map.1 = ""
|
||||||
|
name_map.2 = ""
|
||||||
|
name_map.3 = ""
|
||||||
|
all_monitors = false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
| Selector | Description |
|
||||||
|
|-----------------------------|--------------------------------------|
|
||||||
|
| `#workspaces` | Workspaces widget box |
|
||||||
|
| `#workspaces .item` | Workspace button |
|
||||||
|
| `#workspaces .item.focused` | Workspace button (workspace focused) |
|
|
@ -101,20 +101,21 @@ impl Config {
|
||||||
/// parse it and return a new instance of `Self`.
|
/// parse it and return a new instance of `Self`.
|
||||||
#[instrument]
|
#[instrument]
|
||||||
pub fn load() -> Result<Self> {
|
pub fn load() -> Result<Self> {
|
||||||
let config_path = if let Ok(config_path) = env::var("IRONBAR_CONFIG") {
|
let config_path = env::var("IRONBAR_CONFIG").map_or_else(
|
||||||
let path = PathBuf::from(config_path);
|
|_| Self::try_find_config(),
|
||||||
if path.exists() {
|
|config_path| {
|
||||||
Ok(path)
|
let path = PathBuf::from(config_path);
|
||||||
} else {
|
if path.exists() {
|
||||||
Err(Report::msg(format!(
|
Ok(path)
|
||||||
"Specified config file does not exist: {}",
|
} else {
|
||||||
path.display()
|
Err(Report::msg(format!(
|
||||||
))
|
"Specified config file does not exist: {}",
|
||||||
.note("Config file was specified using `IRONBAR_CONFIG` environment variable"))
|
path.display()
|
||||||
}
|
))
|
||||||
} else {
|
.note("Config file was specified using `IRONBAR_CONFIG` environment variable"))
|
||||||
Self::try_find_config()
|
}
|
||||||
}?;
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
Self::load_file(&config_path)
|
Self::load_file(&config_path)
|
||||||
}
|
}
|
||||||
|
@ -141,13 +142,15 @@ impl Config {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
match file {
|
file.map_or_else(
|
||||||
Some(file) => Ok(file),
|
|| {
|
||||||
None => Err(Report::msg("Could not find config file")
|
Err(Report::msg("Could not find config file")
|
||||||
.suggestion("Ironbar does not include a configuration out of the box")
|
.suggestion("Ironbar does not include a configuration out of the box")
|
||||||
.suggestion("A guide on writing a config can be found on the wiki:")
|
.suggestion("A guide on writing a config can be found on the wiki:")
|
||||||
.suggestion("https://github.com/JakeStanger/ironbar/wiki/configuration-guide")),
|
.suggestion("https://github.com/JakeStanger/ironbar/wiki/configuration-guide"))
|
||||||
}
|
},
|
||||||
|
Ok,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads the config file at the specified path
|
/// Loads the config file at the specified path
|
||||||
|
|
23
src/icon.rs
23
src/icon.rs
|
@ -68,17 +68,12 @@ fn parse_desktop_file(path: PathBuf) -> io::Result<HashMap<String, String>> {
|
||||||
|
|
||||||
/// Attempts to get the icon name from the app's `.desktop` file.
|
/// Attempts to get the icon name from the app's `.desktop` file.
|
||||||
fn get_desktop_icon_name(app_id: &str) -> Option<String> {
|
fn get_desktop_icon_name(app_id: &str) -> Option<String> {
|
||||||
match find_desktop_file(app_id) {
|
find_desktop_file(app_id).and_then(|file| {
|
||||||
Some(file) => {
|
let map = parse_desktop_file(file);
|
||||||
let map = parse_desktop_file(file);
|
map.map_or(None, |map| {
|
||||||
|
map.get("Icon").map(std::string::ToString::to_string)
|
||||||
match map {
|
})
|
||||||
Ok(map) => map.get("Icon").map(std::string::ToString::to_string),
|
})
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum IconLocation {
|
enum IconLocation {
|
||||||
|
@ -137,11 +132,7 @@ pub fn get_icon(theme: &IconTheme, app_id: &str, size: i32) -> Option<Pixbuf> {
|
||||||
match icon_location {
|
match icon_location {
|
||||||
Some(IconLocation::Theme(icon_name)) => {
|
Some(IconLocation::Theme(icon_name)) => {
|
||||||
let icon = theme.load_icon(&icon_name, size, IconLookupFlags::FORCE_SIZE);
|
let icon = theme.load_icon(&icon_name, size, IconLookupFlags::FORCE_SIZE);
|
||||||
|
icon.map_or(None, |icon| icon)
|
||||||
match icon {
|
|
||||||
Ok(icon) => icon,
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Some(IconLocation::File(path)) => Pixbuf::from_file_at_scale(path, size, size, true).ok(),
|
Some(IconLocation::File(path)) => Pixbuf::from_file_at_scale(path, size, size, true).ok(),
|
||||||
None => None,
|
None => None,
|
||||||
|
|
|
@ -81,18 +81,20 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||||
mut rx: Receiver<Self::ReceiveMessage>,
|
mut rx: Receiver<Self::ReceiveMessage>,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
let items = match &self.favorites {
|
let items = self
|
||||||
Some(favorites) => favorites
|
.favorites
|
||||||
.iter()
|
.as_ref()
|
||||||
.map(|app_id| {
|
.map_or_else(IndexMap::new, |favorites| {
|
||||||
(
|
favorites
|
||||||
app_id.to_string(),
|
.iter()
|
||||||
Item::new(app_id.to_string(), OpenState::Closed, true),
|
.map(|app_id| {
|
||||||
)
|
(
|
||||||
})
|
app_id.to_string(),
|
||||||
.collect::<IndexMap<_, _>>(),
|
Item::new(app_id.to_string(), OpenState::Closed, true),
|
||||||
None => IndexMap::new(),
|
)
|
||||||
};
|
})
|
||||||
|
.collect::<IndexMap<_, _>>()
|
||||||
|
});
|
||||||
|
|
||||||
let items = Arc::new(Mutex::new(items));
|
let items = Arc::new(Mutex::new(items));
|
||||||
|
|
||||||
|
|
|
@ -141,10 +141,9 @@ async fn try_get_mpd_conn(host: &str) -> Result<Connection, MpdProtocolError> {
|
||||||
fn is_unix_socket(host: &str) -> bool {
|
fn is_unix_socket(host: &str) -> bool {
|
||||||
let path = PathBuf::from(host);
|
let path = PathBuf::from(host);
|
||||||
path.exists()
|
path.exists()
|
||||||
&& match path.metadata() {
|
&& path
|
||||||
Ok(metadata) => metadata.file_type().is_socket(),
|
.metadata()
|
||||||
Err(_) => false,
|
.map_or(false, |metadata| metadata.file_type().is_socket())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn connect_unix(host: &str) -> Result<Connection, MpdProtocolError> {
|
async fn connect_unix(host: &str) -> Result<Connection, MpdProtocolError> {
|
||||||
|
|
|
@ -97,10 +97,7 @@ fn default_music_dir() -> PathBuf {
|
||||||
/// Attempts to read the first value for a tag
|
/// Attempts to read the first value for a tag
|
||||||
/// (since the MPD client returns a vector of tags, or None)
|
/// (since the MPD client returns a vector of tags, or None)
|
||||||
pub fn try_get_first_tag(vec: Option<&Vec<String>>) -> Option<&str> {
|
pub fn try_get_first_tag(vec: Option<&Vec<String>>) -> Option<&str> {
|
||||||
match vec {
|
vec.and_then(|vec| vec.first().map(String::as_str))
|
||||||
Some(vec) => vec.first().map(String::as_str),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Formats a duration given in seconds
|
/// Formats a duration given in seconds
|
||||||
|
@ -369,11 +366,14 @@ impl Module<Button> for MpdModule {
|
||||||
.join("cover.jpg"),
|
.join("cover.jpg"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(pixbuf) = Pixbuf::from_file_at_scale(cover_path, 128, 128, true) {
|
Pixbuf::from_file_at_scale(cover_path, 128, 128, true).map_or_else(
|
||||||
album_image.set_from_pixbuf(Some(&pixbuf));
|
|_| {
|
||||||
} else {
|
album_image.set_from_pixbuf(None);
|
||||||
album_image.set_from_pixbuf(None);
|
},
|
||||||
}
|
|pixbuf| {
|
||||||
|
album_image.set_from_pixbuf(Some(&pixbuf));
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
title_label
|
title_label
|
||||||
|
|
|
@ -359,7 +359,7 @@ fn refresh_disk_tokens(format_info: &mut HashMap<String, String>, sys: &mut Syst
|
||||||
let key = disk
|
let key = disk
|
||||||
.mount_point()
|
.mount_point()
|
||||||
.to_str()
|
.to_str()
|
||||||
.map(|s| s.replace('{', "").replace('}', ""));
|
.map(|s| s.replace(['{', '}'], ""));
|
||||||
|
|
||||||
if let Some(key) = key {
|
if let Some(key) = key {
|
||||||
let total = disk.total_space();
|
let total = disk.total_space();
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub struct TrayModule;
|
||||||
fn get_icon(item: &StatusNotifierItem) -> Option<Image> {
|
fn get_icon(item: &StatusNotifierItem) -> Option<Image> {
|
||||||
item.icon_theme_path.as_ref().and_then(|path| {
|
item.icon_theme_path.as_ref().and_then(|path| {
|
||||||
let theme = IconTheme::new();
|
let theme = IconTheme::new();
|
||||||
theme.append_search_path(&path);
|
theme.append_search_path(path);
|
||||||
|
|
||||||
item.icon_name.as_ref().and_then(|icon_name| {
|
item.icon_name.as_ref().and_then(|icon_name| {
|
||||||
let icon_info = theme.lookup_icon(icon_name, 16, IconLookupFlags::empty());
|
let icon_info = theme.lookup_icon(icon_name, 16, IconLookupFlags::empty());
|
||||||
|
|
|
@ -3,7 +3,8 @@ use color_eyre::{Help, Report, Result};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
/// Attempts to execute a given command.
|
/// Attempts to execute a given command,
|
||||||
|
/// waiting for it to finish.
|
||||||
/// If the command returns status 0,
|
/// If the command returns status 0,
|
||||||
/// the `stdout` is returned.
|
/// the `stdout` is returned.
|
||||||
/// Otherwise, an `Err` variant
|
/// Otherwise, an `Err` variant
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue