mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-04-19 19:34:24 +02:00
parent
1320639d4e
commit
d20972cb32
7 changed files with 79 additions and 36 deletions
|
@ -279,10 +279,10 @@ The following table lists each of the top-level bar config options:
|
||||||
The following table lists each of the module-level options that are present on **all** modules.
|
The following table lists each of the module-level options that are present on **all** modules.
|
||||||
For details on available modules and each of their config options, check the sidebar.
|
For details on available modules and each of their config options, check the sidebar.
|
||||||
|
|
||||||
For information on the `Script` type, see [here](script).
|
For information on the `Script` type, and embedding scripts in strings, see [here](script).
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|------------|--------------------|---------|--------------------------------------------------------------------------------------------------------------------|
|
|------------|--------------------|---------|--------------------------------------------------------------------------------------------------------------------|
|
||||||
| `show_if` | `Script [polling]` | `null` | Polls the script to check its exit code. If exit code is zero, the module is shown. For other codes, it is hidden. |
|
| `show_if` | `Script [polling]` | `null` | Polls the script to check its exit code. If exit code is zero, the module is shown. For other codes, it is hidden. |
|
||||||
| `on_click` | `Script [polling]` | `null` | Runs the script when the module is clicked. |
|
| `on_click` | `Script [polling]` | `null` | Runs the script when the module is clicked. |
|
||||||
| `tooltip` | `string` | `null` | Shows this text on hover. |
|
| `tooltip` | `string` | `null` | Shows this text on hover. Supports embedding scripts between `{{double braces}}`. |
|
||||||
|
|
|
@ -42,6 +42,17 @@ For example:
|
||||||
poll:5000:uptime -p | cut -d ' ' -f2-
|
poll:5000:uptime -p | cut -d ' ' -f2-
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Embedding
|
||||||
|
|
||||||
|
Some string config options support "embedding scripts". This allows you to mix static/dynamic content.
|
||||||
|
An example of this is the common `tooltip` option.
|
||||||
|
|
||||||
|
Scripts can be embedded in these cases using `{{double braces}}` and the shorthand syntax:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"Up: {{30000:uptime -p | cut -d ' ' -f2-}}"
|
||||||
|
```
|
||||||
|
|
||||||
### Longhand (object)
|
### Longhand (object)
|
||||||
|
|
||||||
An object consisting of the `cmd` key and optionally the `mode` and/or `interval` keys.
|
An object consisting of the `cmd` key and optionally the `mode` and/or `interval` keys.
|
||||||
|
|
|
@ -67,6 +67,8 @@ let {
|
||||||
{ type = "label" name = "uptime" label = "Up: {{30000:uptime -p | cut -d ' ' -f2-}}" }
|
{ type = "label" name = "uptime" label = "Up: {{30000:uptime -p | cut -d ' ' -f2-}}" }
|
||||||
]
|
]
|
||||||
} ]
|
} ]
|
||||||
|
|
||||||
|
tooltip = "Up: {{30000:uptime -p | cut -d ' ' -f2-}}"
|
||||||
}
|
}
|
||||||
|
|
||||||
$left = [ $workspaces $launcher ]
|
$left = [ $workspaces $launcher ]
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::modules::workspaces::WorkspaceUpdate;
|
||||||
use crate::modules::{Module, ModuleInfoBuilder, ModuleLocation, ModuleUpdateEvent, WidgetContext};
|
use crate::modules::{Module, ModuleInfoBuilder, ModuleLocation, ModuleUpdateEvent, WidgetContext};
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::script::{OutputStream, Script};
|
use crate::script::{OutputStream, Script};
|
||||||
|
use crate::widgets::DynamicString;
|
||||||
use crate::{await_sync, Config};
|
use crate::{await_sync, Config};
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
|
@ -212,7 +213,10 @@ fn add_modules(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(tooltip) = common.tooltip {
|
if let Some(tooltip) = common.tooltip {
|
||||||
container.set_tooltip_text(Some(&tooltip));
|
DynamicString::new(&tooltip, move |string| {
|
||||||
|
container.set_tooltip_text(Some(&string));
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let has_popup = widget.popup.is_some();
|
let has_popup = widget.popup.is_some();
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::config::CommonConfig;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
use crate::popup::{ButtonGeometry, Popup};
|
use crate::popup::{ButtonGeometry, Popup};
|
||||||
use crate::script::Script;
|
use crate::script::Script;
|
||||||
use crate::widgets::DynamicLabel;
|
use crate::widgets::DynamicString;
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, Label, Orientation};
|
use gtk::{Button, Label, Orientation};
|
||||||
|
@ -61,7 +61,7 @@ impl Widget {
|
||||||
fn add_to(self, parent: >k::Box, tx: Sender<ExecEvent>, bar_orientation: Orientation) {
|
fn add_to(self, parent: >k::Box, tx: Sender<ExecEvent>, bar_orientation: Orientation) {
|
||||||
match self.widget_type {
|
match self.widget_type {
|
||||||
WidgetType::Box => parent.add(&self.into_box(&tx, bar_orientation)),
|
WidgetType::Box => parent.add(&self.into_box(&tx, bar_orientation)),
|
||||||
WidgetType::Label => parent.add(&self.into_label().label),
|
WidgetType::Label => parent.add(&self.into_label()),
|
||||||
WidgetType::Button => parent.add(&self.into_button(tx, bar_orientation)),
|
WidgetType::Button => parent.add(&self.into_button(tx, bar_orientation)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ impl Widget {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `gtk::Label` from this widget
|
/// Creates a `gtk::Label` from this widget
|
||||||
fn into_label(self) -> DynamicLabel {
|
fn into_label(self) -> Label {
|
||||||
let mut builder = Label::builder().use_markup(true);
|
let mut builder = Label::builder().use_markup(true);
|
||||||
|
|
||||||
if let Some(name) = self.name {
|
if let Some(name) = self.name {
|
||||||
|
@ -110,7 +110,17 @@ impl Widget {
|
||||||
|
|
||||||
let text = self.label.map_or_else(String::new, |text| text);
|
let text = self.label.map_or_else(String::new, |text| text);
|
||||||
|
|
||||||
DynamicLabel::new(label, &text)
|
{
|
||||||
|
let label = label.clone();
|
||||||
|
DynamicString::new(&text, move |string| {
|
||||||
|
label.set_label(&string);
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
label
|
||||||
|
|
||||||
|
// DynamicString::new(label, &text)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `gtk::Button` from this widget
|
/// Creates a `gtk::Button` from this widget
|
||||||
|
|
|
@ -5,17 +5,20 @@ use std::sync::{Arc, Mutex};
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum DynamicLabelSegment {
|
enum DynamicStringSegment {
|
||||||
Static(String),
|
Static(String),
|
||||||
Dynamic(Script),
|
Dynamic(Script),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DynamicLabel {
|
pub struct DynamicString {
|
||||||
pub label: gtk::Label,
|
// pub label: gtk::Label,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DynamicLabel {
|
impl DynamicString {
|
||||||
pub fn new(label: gtk::Label, input: &str) -> Self {
|
pub fn new<F>(input: &str, f: F) -> Self
|
||||||
|
where
|
||||||
|
F: FnMut(String) -> Continue + 'static,
|
||||||
|
{
|
||||||
let mut segments = vec![];
|
let mut segments = vec![];
|
||||||
|
|
||||||
let mut chars = input.chars().collect::<Vec<_>>();
|
let mut chars = input.chars().collect::<Vec<_>>();
|
||||||
|
@ -36,7 +39,7 @@ impl DynamicLabel {
|
||||||
let len = str.len();
|
let len = str.len();
|
||||||
|
|
||||||
(
|
(
|
||||||
DynamicLabelSegment::Dynamic(Script::from(str.as_str())),
|
DynamicStringSegment::Dynamic(Script::from(str.as_str())),
|
||||||
len + SKIP_BRACKETS,
|
len + SKIP_BRACKETS,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -49,7 +52,7 @@ impl DynamicLabel {
|
||||||
|
|
||||||
let len = str.len();
|
let len = str.len();
|
||||||
|
|
||||||
(DynamicLabelSegment::Static(str), len)
|
(DynamicStringSegment::Static(str), len)
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ne!(skip, 0);
|
assert_ne!(skip, 0);
|
||||||
|
@ -63,13 +66,13 @@ impl DynamicLabel {
|
||||||
|
|
||||||
for (i, segment) in segments.into_iter().enumerate() {
|
for (i, segment) in segments.into_iter().enumerate() {
|
||||||
match segment {
|
match segment {
|
||||||
DynamicLabelSegment::Static(str) => {
|
DynamicStringSegment::Static(str) => {
|
||||||
label_parts
|
label_parts
|
||||||
.lock()
|
.lock()
|
||||||
.expect("Failed to get lock on label parts")
|
.expect("Failed to get lock on label parts")
|
||||||
.insert(i, str);
|
.insert(i, str);
|
||||||
}
|
}
|
||||||
DynamicLabelSegment::Dynamic(script) => {
|
DynamicStringSegment::Dynamic(script) => {
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
let label_parts = label_parts.clone();
|
let label_parts = label_parts.clone();
|
||||||
|
|
||||||
|
@ -77,11 +80,21 @@ impl DynamicLabel {
|
||||||
script
|
script
|
||||||
.run(|(out, _)| {
|
.run(|(out, _)| {
|
||||||
if let OutputStream::Stdout(out) = out {
|
if let OutputStream::Stdout(out) = out {
|
||||||
label_parts
|
let mut label_parts = label_parts
|
||||||
.lock()
|
.lock()
|
||||||
.expect("Failed to get lock on label parts")
|
.expect("Failed to get lock on label parts");
|
||||||
|
|
||||||
|
label_parts
|
||||||
|
// .lock()
|
||||||
|
// .expect("Failed to get lock on label parts")
|
||||||
.insert(i, out);
|
.insert(i, out);
|
||||||
tx.send(()).expect("Failed to send update");
|
|
||||||
|
let string = label_parts
|
||||||
|
.iter()
|
||||||
|
.map(|(_, part)| part.as_str())
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
|
tx.send(string).expect("Failed to send update");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
@ -90,25 +103,22 @@ impl DynamicLabel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.send(()).expect("Failed to send update");
|
// initialize
|
||||||
|
|
||||||
{
|
{
|
||||||
let label = label.clone();
|
let label_parts = label_parts
|
||||||
rx.attach(None, move |_| {
|
.lock()
|
||||||
let new_label = label_parts
|
.expect("Failed to get lock on label parts")
|
||||||
.lock()
|
.iter()
|
||||||
.expect("Failed to get lock on label parts")
|
.map(|(_, part)| part.as_str())
|
||||||
.iter()
|
.collect::<String>();
|
||||||
.map(|(_, part)| part.as_str())
|
|
||||||
.collect::<String>();
|
|
||||||
|
|
||||||
label.set_label(new_label.as_str());
|
tx.send(label_parts).expect("Failed to send update");
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { label }
|
rx.attach(None, f);
|
||||||
|
|
||||||
|
// Self { label }
|
||||||
|
Self {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +131,13 @@ mod tests {
|
||||||
// TODO: see if we can run gtk tests in ci
|
// TODO: see if we can run gtk tests in ci
|
||||||
if gtk::init().is_ok() {
|
if gtk::init().is_ok() {
|
||||||
let label = gtk::Label::new(None);
|
let label = gtk::Label::new(None);
|
||||||
DynamicLabel::new(label, "Uptime: {{1000:uptime -p | cut -d ' ' -f2-}}");
|
DynamicString::new(
|
||||||
|
"Uptime: {{1000:uptime -p | cut -d ' ' -f2-}}",
|
||||||
|
move |string| {
|
||||||
|
label.set_label(string);
|
||||||
|
Continue(true)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
mod dynamic_label;
|
mod dynamic_label;
|
||||||
|
|
||||||
pub use dynamic_label::DynamicLabel;
|
pub use dynamic_label::DynamicString;
|
||||||
|
|
Loading…
Add table
Reference in a new issue