mirror of
				https://github.com/Zedfrigg/ironbar.git
				synced 2025-11-03 23:11:54 +01: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
		Add a link
		
	
		Reference in a new issue