mirror of
https://github.com/JakeStanger/ironbar.git
synced 2024-11-22 05:34:35 +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:
|
The CLI supports plaintext and JSON output. Plaintext will:
|
||||||
|
|
||||||
- Print `ok` for empty success responses
|
- 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`.
|
- Print `error` to followed by the error on the next line for error responses. This is printed to `stderr`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -150,6 +151,9 @@ Each key/value pair is on its own `\n` separated newline. The key and value are
|
|||||||
|
|
||||||
### `bar`
|
### `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`
|
#### `show`
|
||||||
|
|
||||||
Forces a bar to be shown, regardless of the current visibility state.
|
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`
|
### `error`
|
||||||
|
|
||||||
The operation failed.
|
The operation failed.
|
||||||
@ -335,4 +350,4 @@ Message is optional.
|
|||||||
"type": "error",
|
"type": "error",
|
||||||
"message": "lorem ipsum"
|
"message": "lorem ipsum"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -46,6 +46,7 @@ pub fn handle_response(response: Response, format: Format) {
|
|||||||
Format::Plain => match response {
|
Format::Plain => match response {
|
||||||
Response::Ok => println!("ok"),
|
Response::Ok => println!("ok"),
|
||||||
Response::OkValue { value } => println!("{value}"),
|
Response::OkValue { value } => println!("{value}"),
|
||||||
|
Response::Multi { values } => println!("{}", values.join("\n")),
|
||||||
Response::Err { message } => eprintln!("error\n{}", message.unwrap_or_default()),
|
Response::Err { message } => eprintln!("error\n{}", message.unwrap_or_default()),
|
||||||
},
|
},
|
||||||
Format::Json => println!(
|
Format::Json => println!(
|
||||||
|
@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
pub enum Response {
|
pub enum Response {
|
||||||
Ok,
|
Ok,
|
||||||
OkValue { value: String },
|
OkValue { value: String },
|
||||||
|
Multi { values: Vec<String> },
|
||||||
Err { message: Option<String> },
|
Err { message: Option<String> },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,48 +8,60 @@ use std::rc::Rc;
|
|||||||
pub fn handle_command(command: BarCommand, ironbar: &Rc<Ironbar>) -> Response {
|
pub fn handle_command(command: BarCommand, ironbar: &Rc<Ironbar>) -> Response {
|
||||||
use BarCommandType::*;
|
use BarCommandType::*;
|
||||||
|
|
||||||
let bar = ironbar.bar_by_name(&command.name);
|
let bars = ironbar.bars_by_name(&command.name);
|
||||||
let Some(bar) = bar else {
|
|
||||||
return Response::error("Invalid bar name");
|
|
||||||
};
|
|
||||||
|
|
||||||
match command.subcommand {
|
bars.into_iter()
|
||||||
Show => set_visible(&bar, true),
|
.map(|bar| match &command.subcommand {
|
||||||
Hide => set_visible(&bar, false),
|
Show => set_visible(&bar, true),
|
||||||
SetVisible { visible } => set_visible(&bar, visible),
|
Hide => set_visible(&bar, false),
|
||||||
ToggleVisible => set_visible(&bar, !bar.visible()),
|
SetVisible { visible } => set_visible(&bar, *visible),
|
||||||
GetVisible => Response::OkValue {
|
ToggleVisible => set_visible(&bar, !bar.visible()),
|
||||||
value: bar.visible().to_string(),
|
GetVisible => Response::OkValue {
|
||||||
},
|
value: bar.visible().to_string(),
|
||||||
|
},
|
||||||
ShowPopup { widget_name } => show_popup(&bar, &widget_name),
|
ShowPopup { widget_name } => show_popup(&bar, widget_name),
|
||||||
HidePopup => hide_popup(&bar),
|
HidePopup => hide_popup(&bar),
|
||||||
SetPopupVisible {
|
SetPopupVisible {
|
||||||
widget_name,
|
widget_name,
|
||||||
visible,
|
visible,
|
||||||
} => {
|
} => {
|
||||||
if visible {
|
if *visible {
|
||||||
show_popup(&bar, &widget_name)
|
show_popup(&bar, widget_name)
|
||||||
} else {
|
} else {
|
||||||
hide_popup(&bar)
|
hide_popup(&bar)
|
||||||
|
};
|
||||||
|
Response::Ok
|
||||||
}
|
}
|
||||||
}
|
TogglePopup { widget_name } => {
|
||||||
TogglePopup { widget_name } => {
|
if bar.popup().visible() {
|
||||||
if bar.popup().visible() {
|
hide_popup(&bar)
|
||||||
hide_popup(&bar)
|
} else {
|
||||||
} else {
|
show_popup(&bar, widget_name)
|
||||||
show_popup(&bar, &widget_name)
|
};
|
||||||
|
Response::Ok
|
||||||
}
|
}
|
||||||
}
|
GetPopupVisible => Response::OkValue {
|
||||||
GetPopupVisible => Response::OkValue {
|
value: bar.popup().visible().to_string(),
|
||||||
value: bar.popup().visible().to_string(),
|
},
|
||||||
},
|
SetExclusive { exclusive } => {
|
||||||
SetExclusive { exclusive } => {
|
bar.set_exclusive(*exclusive);
|
||||||
bar.set_exclusive(exclusive);
|
Response::Ok
|
||||||
|
}
|
||||||
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 {
|
fn set_visible(bar: &Bar, visible: bool) -> Response {
|
||||||
|
@ -267,17 +267,18 @@ impl Ironbar {
|
|||||||
.clone()
|
.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.
|
/// the clone is cheap enough to not worry about.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn bar_by_name(&self, name: &str) -> Option<Bar> {
|
pub fn bars_by_name(&self, name: &str) -> Vec<Bar> {
|
||||||
self.bars
|
self.bars
|
||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&bar| bar.name() == name)
|
.filter(|&bar| bar.name() == name)
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Re-reads the config file from disk and replaces the active config.
|
/// Re-reads the config file from disk and replaces the active config.
|
||||||
|
Loading…
Reference in New Issue
Block a user