Implement command (fixes #9)
This commit is contained in:
parent
3d07a84d1b
commit
0ea3d2255b
4 changed files with 80 additions and 41 deletions
46
src/app.rs
46
src/app.rs
|
@ -1,12 +1,19 @@
|
|||
use crate::config::WindowStacking;
|
||||
use crate::{config, script_var_handler::*, util, widgets};
|
||||
use crate::{config::WindowName, util::Coords, value::PrimitiveValue};
|
||||
use crate::{eww_state, value::VarName};
|
||||
use crate::{
|
||||
config,
|
||||
config::{WindowName, WindowStacking},
|
||||
eww_state,
|
||||
script_var_handler::*,
|
||||
util,
|
||||
util::Coords,
|
||||
value::{PrimitiveValue, VarName},
|
||||
widgets,
|
||||
};
|
||||
use anyhow::*;
|
||||
use crossbeam_channel::Sender;
|
||||
use crossbeam_channel;
|
||||
use debug_stub_derive::*;
|
||||
use gdk::WindowExt;
|
||||
use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt};
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -23,7 +30,7 @@ pub enum EwwCommand {
|
|||
window_name: WindowName,
|
||||
},
|
||||
KillServer,
|
||||
PrintState,
|
||||
PrintState(crossbeam_channel::Sender<String>),
|
||||
}
|
||||
|
||||
#[derive(DebugStub)]
|
||||
|
@ -38,7 +45,7 @@ pub struct App {
|
|||
}
|
||||
|
||||
impl App {
|
||||
pub fn handle_command(&mut self, event: EwwCommand, response_sender: Option<Sender<String>>) {
|
||||
pub fn handle_command(&mut self, event: EwwCommand) {
|
||||
log::debug!("Handling event: {:?}", &event);
|
||||
let result: Result<_> = match event {
|
||||
EwwCommand::UpdateVar(key, value) => self.update_state(key, value),
|
||||
|
@ -50,16 +57,18 @@ impl App {
|
|||
}
|
||||
EwwCommand::OpenWindow { window_name, pos, size } => self.open_window(&window_name, pos, size),
|
||||
EwwCommand::CloseWindow { window_name } => self.close_window(&window_name),
|
||||
EwwCommand::PrintState => Ok(()),
|
||||
EwwCommand::PrintState(sender) => {
|
||||
let output = self
|
||||
.eww_state
|
||||
.get_variables()
|
||||
.iter()
|
||||
.map(|(key, value)| format!("{}: {}", key, value))
|
||||
.join("\n");
|
||||
sender.send(output).context("sending response from main thread")
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(err) = result {
|
||||
if let Some(response_sender) = response_sender {
|
||||
let _ = response_sender.send(format!("Error while handling event: {:?}", err));
|
||||
} else {
|
||||
eprintln!("Error while handling event: {:?}", err);
|
||||
}
|
||||
}
|
||||
util::print_result_err("while handling event", &result);
|
||||
}
|
||||
|
||||
fn update_state(&mut self, fieldname: VarName, value: PrimitiveValue) -> Result<()> {
|
||||
|
@ -144,9 +153,10 @@ impl App {
|
|||
|
||||
pub fn reload_all_windows(&mut self, config: config::EwwConfig) -> Result<()> {
|
||||
// refresh script-var poll stuff
|
||||
if let Err(e) = self.script_var_handler.initialize_clean(config.get_script_vars().clone()) {
|
||||
eprintln!("Error while setting up script-var commands: {:?}", e);
|
||||
}
|
||||
util::print_result_err(
|
||||
"while setting up script-var commands",
|
||||
&self.script_var_handler.initialize_clean(config.get_script_vars().clone()),
|
||||
);
|
||||
|
||||
self.eww_config = config;
|
||||
self.eww_state.clear_all_window_states();
|
||||
|
|
|
@ -76,6 +76,10 @@ impl EwwState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_variables(&self) -> &HashMap<VarName, PrimitiveValue> {
|
||||
&self.variables_state
|
||||
}
|
||||
|
||||
/// remove all state stored specific to one window
|
||||
pub fn clear_window_state(&mut self, window_name: &WindowName) {
|
||||
self.windows.remove(window_name);
|
||||
|
|
64
src/main.rs
64
src/main.rs
|
@ -9,9 +9,6 @@ extern crate gtk;
|
|||
|
||||
use anyhow::*;
|
||||
use eww_state::*;
|
||||
use gdk::*;
|
||||
use gtk::prelude::*;
|
||||
use hotwatch;
|
||||
use log;
|
||||
use pretty_env_logger;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -79,10 +76,10 @@ pub struct Opt {
|
|||
}
|
||||
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum OptAction {
|
||||
#[structopt(name = "update")]
|
||||
#[structopt(name = "update", help = "update the value of a variable")]
|
||||
Update { fieldname: VarName, value: PrimitiveValue },
|
||||
|
||||
#[structopt(name = "open")]
|
||||
#[structopt(name = "open", help = "open a window")]
|
||||
OpenWindow {
|
||||
window_name: config::WindowName,
|
||||
|
||||
|
@ -93,24 +90,27 @@ pub enum OptAction {
|
|||
size: Option<util::Coords>,
|
||||
},
|
||||
|
||||
#[structopt(name = "close")]
|
||||
#[structopt(name = "close", help = "close the window with the given name")]
|
||||
CloseWindow { window_name: config::WindowName },
|
||||
|
||||
#[structopt(name = "kill")]
|
||||
#[structopt(name = "kill", help = "kill the eww daemon")]
|
||||
KillServer,
|
||||
|
||||
#[structopt(name = "state")]
|
||||
#[structopt(name = "state", help = "Print the current eww-state")]
|
||||
ShowState,
|
||||
}
|
||||
|
||||
impl Into<app::EwwCommand> for OptAction {
|
||||
fn into(self) -> app::EwwCommand {
|
||||
impl OptAction {
|
||||
fn into_eww_command(self) -> (app::EwwCommand, Option<crossbeam_channel::Receiver<String>>) {
|
||||
match self {
|
||||
OptAction::Update { fieldname, value } => app::EwwCommand::UpdateVar(fieldname, value),
|
||||
OptAction::OpenWindow { window_name, pos, size } => app::EwwCommand::OpenWindow { window_name, pos, size },
|
||||
OptAction::CloseWindow { window_name } => app::EwwCommand::CloseWindow { window_name },
|
||||
OptAction::KillServer => app::EwwCommand::KillServer,
|
||||
OptAction::ShowState => unimplemented!(),
|
||||
OptAction::Update { fieldname, value } => (app::EwwCommand::UpdateVar(fieldname, value), None),
|
||||
OptAction::OpenWindow { window_name, pos, size } => (app::EwwCommand::OpenWindow { window_name, pos, size }, None),
|
||||
OptAction::CloseWindow { window_name } => (app::EwwCommand::CloseWindow { window_name }, None),
|
||||
OptAction::KillServer => (app::EwwCommand::KillServer, None),
|
||||
OptAction::ShowState => {
|
||||
let (send, recv) = crossbeam_channel::unbounded();
|
||||
(app::EwwCommand::PrintState(send), Some(recv))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,10 @@ fn try_main() -> Result<()> {
|
|||
if let Ok(mut stream) = net::UnixStream::connect(&*IPC_SOCKET_PATH) {
|
||||
log::info!("Forwarding options to server");
|
||||
stream.write_all(&bincode::serialize(&opts)?)?;
|
||||
|
||||
let mut buf = String::new();
|
||||
stream.read_to_string(&mut buf)?;
|
||||
println!("{}", buf);
|
||||
} else {
|
||||
log::info!("No instance found... Initializing server.");
|
||||
|
||||
|
@ -175,13 +179,19 @@ fn initialize_server(opts: Opt) -> Result<()> {
|
|||
}
|
||||
|
||||
// run the command that eww was started with
|
||||
app.handle_command(opts.action.into(), None);
|
||||
let (command, maybe_response_recv) = opts.action.into_eww_command();
|
||||
app.handle_command(command);
|
||||
if let Some(response_recv) = maybe_response_recv {
|
||||
if let Ok(response) = response_recv.recv_timeout(std::time::Duration::from_millis(100)) {
|
||||
println!("{}", response);
|
||||
}
|
||||
}
|
||||
|
||||
run_server_thread(evt_send.clone())?;
|
||||
let _hotwatch = run_filewatch_thread(&config_file_path, &scss_file_path, evt_send.clone())?;
|
||||
|
||||
evt_recv.attach(None, move |msg| {
|
||||
app.handle_command(msg, None);
|
||||
app.handle_command(msg);
|
||||
glib::Continue(true)
|
||||
});
|
||||
|
||||
|
@ -196,9 +206,19 @@ fn run_server_thread(evt_send: glib::Sender<app::EwwCommand>) -> Result<()> {
|
|||
log::info!("Starting up eww server");
|
||||
let listener = net::UnixListener::bind(&*IPC_SOCKET_PATH)?;
|
||||
for stream in listener.incoming() {
|
||||
let command: Opt = bincode::deserialize_from(stream?)?;
|
||||
log::info!("received command from IPC: {:?}", &command);
|
||||
evt_send.send(command.action.into())?;
|
||||
try_logging_errors!("handling message from IPC client" => {
|
||||
let mut stream = stream?;
|
||||
let opts: Opt = bincode::deserialize_from(&stream)?;
|
||||
log::info!("received command from IPC: {:?}", &opts);
|
||||
let (command, maybe_response_recv) = opts.action.into_eww_command();
|
||||
evt_send.send(command)?;
|
||||
if let Some(response_recv) = maybe_response_recv {
|
||||
if let Ok(response) = response_recv.recv_timeout(std::time::Duration::from_millis(100)) {
|
||||
let result = &stream.write_all(response.as_bytes());
|
||||
util::print_result_err("Sending text response to ipc client", &result);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
if let Err(err) = result {
|
||||
|
@ -233,9 +253,7 @@ fn run_filewatch_thread<P: AsRef<Path>>(
|
|||
evt_send.send(app::EwwCommand::ReloadCss(eww_css))?;
|
||||
})
|
||||
});
|
||||
if let Err(e) = result {
|
||||
eprintln!("WARN: error while loading CSS file for hot-reloading: \n{}", e)
|
||||
};
|
||||
util::print_result_err("while loading CSS file for hot-reloading", &result);
|
||||
Ok(hotwatch)
|
||||
}
|
||||
|
||||
|
|
|
@ -79,3 +79,10 @@ pub fn replace_env_var_references(input: String) -> String {
|
|||
})
|
||||
.into_owned()
|
||||
}
|
||||
|
||||
/// If the given result is `Err`, prints out the error value using `{:?}`
|
||||
pub fn print_result_err<T, E: std::fmt::Debug>(context: &str, result: &std::result::Result<T, E>) {
|
||||
if let Err(err) = result {
|
||||
eprintln!("Error {}: {:?}", context, err);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue