mirror of
https://github.com/JakeStanger/ironbar.git
synced 2024-11-25 02:50:31 +03:00
fix(ipc): support querying against duplicate bar names
It is possible/valid to define multiple bars by the same name by setting `name` on the top-level bar object, but not specifying monitors. This updates IPC to support this scenario. Allow IPC to act on multiple bars by the same name (#777)
This commit is contained in:
parent
e7c56ee09b
commit
42e25f5ef2
@ -10,7 +10,8 @@ You can also view help per sub-command or command, for example using `ironbar va
|
||||
The CLI supports plaintext and JSON output. Plaintext will:
|
||||
|
||||
- Print `ok` for empty success responses
|
||||
- Print the returned body for success responses
|
||||
- Print the returned body for each success response
|
||||
- Some commands act on multiple objects, in which case the CLI will print one line for each body.
|
||||
- Print `error` to followed by the error on the next line for error responses. This is printed to `stderr`.
|
||||
|
||||
Example:
|
||||
@ -150,6 +151,9 @@ Each key/value pair is on its own `\n` separated newline. The key and value are
|
||||
|
||||
### `bar`
|
||||
|
||||
> [!NOTE]
|
||||
> If there are multiple bars by the same name, the `bar` subcommand will act on all of them and return a `multi` response for commands that get a value.
|
||||
|
||||
#### `show`
|
||||
|
||||
Forces a bar to be shown, regardless of the current visibility state.
|
||||
@ -324,6 +328,17 @@ The operation completed successfully, with response data.
|
||||
}
|
||||
```
|
||||
|
||||
### `multi`
|
||||
|
||||
The operation completed successfully on multiple objects, with response data.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "multi",
|
||||
"values": ["lorem ipsum", "dolor sit"]
|
||||
}
|
||||
```
|
||||
|
||||
### `error`
|
||||
|
||||
The operation failed.
|
||||
|
@ -46,6 +46,7 @@ pub fn handle_response(response: Response, format: Format) {
|
||||
Format::Plain => match response {
|
||||
Response::Ok => println!("ok"),
|
||||
Response::OkValue { value } => println!("{value}"),
|
||||
Response::Multi { values } => println!("{}", values.join("\n")),
|
||||
Response::Err { message } => eprintln!("error\n{}", message.unwrap_or_default()),
|
||||
},
|
||||
Format::Json => println!(
|
||||
|
@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
|
||||
pub enum Response {
|
||||
Ok,
|
||||
OkValue { value: String },
|
||||
Multi { values: Vec<String> },
|
||||
Err { message: Option<String> },
|
||||
}
|
||||
|
||||
|
@ -8,48 +8,60 @@ use std::rc::Rc;
|
||||
pub fn handle_command(command: BarCommand, ironbar: &Rc<Ironbar>) -> Response {
|
||||
use BarCommandType::*;
|
||||
|
||||
let bar = ironbar.bar_by_name(&command.name);
|
||||
let Some(bar) = bar else {
|
||||
return Response::error("Invalid bar name");
|
||||
};
|
||||
let bars = ironbar.bars_by_name(&command.name);
|
||||
|
||||
match command.subcommand {
|
||||
Show => set_visible(&bar, true),
|
||||
Hide => set_visible(&bar, false),
|
||||
SetVisible { visible } => set_visible(&bar, visible),
|
||||
ToggleVisible => set_visible(&bar, !bar.visible()),
|
||||
GetVisible => Response::OkValue {
|
||||
value: bar.visible().to_string(),
|
||||
},
|
||||
|
||||
ShowPopup { widget_name } => show_popup(&bar, &widget_name),
|
||||
HidePopup => hide_popup(&bar),
|
||||
SetPopupVisible {
|
||||
widget_name,
|
||||
visible,
|
||||
} => {
|
||||
if visible {
|
||||
show_popup(&bar, &widget_name)
|
||||
} else {
|
||||
hide_popup(&bar)
|
||||
bars.into_iter()
|
||||
.map(|bar| match &command.subcommand {
|
||||
Show => set_visible(&bar, true),
|
||||
Hide => set_visible(&bar, false),
|
||||
SetVisible { visible } => set_visible(&bar, *visible),
|
||||
ToggleVisible => set_visible(&bar, !bar.visible()),
|
||||
GetVisible => Response::OkValue {
|
||||
value: bar.visible().to_string(),
|
||||
},
|
||||
ShowPopup { widget_name } => show_popup(&bar, widget_name),
|
||||
HidePopup => hide_popup(&bar),
|
||||
SetPopupVisible {
|
||||
widget_name,
|
||||
visible,
|
||||
} => {
|
||||
if *visible {
|
||||
show_popup(&bar, widget_name)
|
||||
} else {
|
||||
hide_popup(&bar)
|
||||
};
|
||||
Response::Ok
|
||||
}
|
||||
}
|
||||
TogglePopup { widget_name } => {
|
||||
if bar.popup().visible() {
|
||||
hide_popup(&bar)
|
||||
} else {
|
||||
show_popup(&bar, &widget_name)
|
||||
TogglePopup { widget_name } => {
|
||||
if bar.popup().visible() {
|
||||
hide_popup(&bar)
|
||||
} else {
|
||||
show_popup(&bar, widget_name)
|
||||
};
|
||||
Response::Ok
|
||||
}
|
||||
}
|
||||
GetPopupVisible => Response::OkValue {
|
||||
value: bar.popup().visible().to_string(),
|
||||
},
|
||||
SetExclusive { exclusive } => {
|
||||
bar.set_exclusive(exclusive);
|
||||
|
||||
Response::Ok
|
||||
}
|
||||
}
|
||||
GetPopupVisible => Response::OkValue {
|
||||
value: bar.popup().visible().to_string(),
|
||||
},
|
||||
SetExclusive { exclusive } => {
|
||||
bar.set_exclusive(*exclusive);
|
||||
Response::Ok
|
||||
}
|
||||
})
|
||||
.reduce(|acc, rsp| match (acc, rsp) {
|
||||
// If all responses are Ok, return one Ok. We assume we'll never mix Ok and OkValue.
|
||||
(Response::Ok, _) => Response::Ok,
|
||||
// Two or more OkValues create a multi:
|
||||
(Response::OkValue { value: v1 }, Response::OkValue { value: v2 }) => Response::Multi {
|
||||
values: vec![v1, v2],
|
||||
},
|
||||
(Response::Multi { mut values }, Response::OkValue { value: v }) => {
|
||||
values.push(v);
|
||||
Response::Multi { values }
|
||||
}
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.unwrap_or(Response::error("Invalid bar name"))
|
||||
}
|
||||
|
||||
fn set_visible(bar: &Bar, visible: bool) -> Response {
|
||||
|
@ -267,17 +267,18 @@ impl Ironbar {
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Gets a clone of a bar by its unique name.
|
||||
/// Gets clones of bars by their name.
|
||||
///
|
||||
/// Since the bar contains mostly GTK objects,
|
||||
/// Since the bars contain mostly GTK objects,
|
||||
/// the clone is cheap enough to not worry about.
|
||||
#[must_use]
|
||||
pub fn bar_by_name(&self, name: &str) -> Option<Bar> {
|
||||
pub fn bars_by_name(&self, name: &str) -> Vec<Bar> {
|
||||
self.bars
|
||||
.borrow()
|
||||
.iter()
|
||||
.find(|&bar| bar.name() == name)
|
||||
.filter(|&bar| bar.name() == name)
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Re-reads the config file from disk and replaces the active config.
|
||||
|
Loading…
Reference in New Issue
Block a user