Add eww logs command. fixes #7

This commit is contained in:
elkowar 2020-10-23 20:17:21 +02:00
parent a906c18bd7
commit e427101c19
2 changed files with 75 additions and 37 deletions

View file

@ -20,6 +20,7 @@ use std::{
io::{Read, Write}, io::{Read, Write},
os::unix::{io::AsRawFd, net}, os::unix::{io::AsRawFd, net},
path::{Path, PathBuf}, path::{Path, PathBuf},
process::Stdio,
}; };
use structopt::StructOpt; use structopt::StructOpt;
use value::Coords; use value::Coords;
@ -82,8 +83,23 @@ pub struct Opt {
#[structopt(short = "-d", long = "--detach")] #[structopt(short = "-d", long = "--detach")]
should_detach: bool, should_detach: bool,
} }
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)] #[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
pub enum OptAction { pub enum OptAction {
#[structopt(flatten)]
ClientOnly(OptActionClientOnly),
#[structopt(flatten)]
WithServer(OptActionWithServer),
}
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
pub enum OptActionClientOnly {
#[structopt(name = "logs", help = "Print and watch the eww logs")]
Logs,
}
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
pub enum OptActionWithServer {
#[structopt(name = "update", help = "update the value of a variable, in a running eww instance")] #[structopt(name = "update", help = "update the value of a variable, in a running eww instance")]
Update { fieldname: VarName, value: PrimitiveValue }, Update { fieldname: VarName, value: PrimitiveValue },
@ -101,7 +117,7 @@ pub enum OptAction {
#[structopt(name = "close", help = "close the window with the given name")] #[structopt(name = "close", help = "close the window with the given name")]
CloseWindow { window_name: WindowName }, CloseWindow { window_name: WindowName },
#[structopt(name = "kill", help = "kill the eww daemon")] #[structopt(name = "kill", help("kill the eww daemon"))]
KillServer, KillServer,
#[structopt(name = "state", help = "Print the current eww-state")] #[structopt(name = "state", help = "Print the current eww-state")]
@ -111,18 +127,18 @@ pub enum OptAction {
ShowDebug, ShowDebug,
} }
impl OptAction { impl OptActionWithServer {
fn into_eww_command(self) -> (app::EwwCommand, Option<crossbeam_channel::Receiver<String>>) { fn into_eww_command(self) -> (app::EwwCommand, Option<crossbeam_channel::Receiver<String>>) {
let command = match self { let command = match self {
OptAction::Update { fieldname, value } => app::EwwCommand::UpdateVar(fieldname, value), OptActionWithServer::Update { fieldname, value } => app::EwwCommand::UpdateVar(fieldname, value),
OptAction::OpenWindow { window_name, pos, size } => app::EwwCommand::OpenWindow { window_name, pos, size }, OptActionWithServer::OpenWindow { window_name, pos, size } => app::EwwCommand::OpenWindow { window_name, pos, size },
OptAction::CloseWindow { window_name } => app::EwwCommand::CloseWindow { window_name }, OptActionWithServer::CloseWindow { window_name } => app::EwwCommand::CloseWindow { window_name },
OptAction::KillServer => app::EwwCommand::KillServer, OptActionWithServer::KillServer => app::EwwCommand::KillServer,
OptAction::ShowState => { OptActionWithServer::ShowState => {
let (send, recv) = crossbeam_channel::unbounded(); let (send, recv) = crossbeam_channel::unbounded();
return (app::EwwCommand::PrintState(send), Some(recv)); return (app::EwwCommand::PrintState(send), Some(recv));
} }
OptAction::ShowDebug => { OptActionWithServer::ShowDebug => {
let (send, recv) = crossbeam_channel::unbounded(); let (send, recv) = crossbeam_channel::unbounded();
return (app::EwwCommand::PrintDebug(send), Some(recv)); return (app::EwwCommand::PrintDebug(send), Some(recv));
} }
@ -130,41 +146,63 @@ impl OptAction {
(command, None) (command, None)
} }
fn is_server_command(&self) -> bool { /// returns true if this command requires a server to already be running
fn needs_server_running(&self) -> bool {
match self { match self {
OptAction::OpenWindow { .. } => true, OptActionWithServer::OpenWindow { .. } => false,
_ => false, _ => true,
} }
} }
} }
fn try_main() -> Result<()> { fn try_main() -> Result<()> {
let opts: Opt = StructOpt::from_args(); let opts: Opt = StructOpt::from_args();
log::info!("Trying to find server process");
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(); match opts.action {
stream.set_read_timeout(Some(std::time::Duration::from_millis(100)))?; OptAction::ClientOnly(action) => {
stream.read_to_string(&mut buf)?; handle_client_only_action(action)?;
println!("{}", buf);
} else {
log::info!("No instance found... Initializing server.");
let _ = std::fs::remove_file(&*IPC_SOCKET_PATH);
if opts.should_detach {
do_detach()?;
} }
OptAction::WithServer(action) => {
log::info!("Trying to find server process");
if let Ok(mut stream) = net::UnixStream::connect(&*IPC_SOCKET_PATH) {
log::info!("Forwarding options to server");
stream.write_all(&bincode::serialize(&action)?)?;
initialize_server(opts)?; let mut buf = String::new();
stream.set_read_timeout(Some(std::time::Duration::from_millis(100)))?;
stream.read_to_string(&mut buf)?;
println!("{}", buf);
} else {
log::info!("No instance found... Initializing server.");
let _ = std::fs::remove_file(&*IPC_SOCKET_PATH);
if opts.should_detach {
do_detach()?;
}
initialize_server(action)?;
}
}
} }
Ok(()) Ok(())
} }
fn initialize_server(opts: Opt) -> Result<()> { fn handle_client_only_action(action: OptActionClientOnly) -> Result<()> {
if !opts.action.is_server_command() { match action {
OptActionClientOnly::Logs => {
std::process::Command::new("tail")
.args(["-f", LOG_FILE.to_string_lossy().as_ref()].iter())
.stdin(Stdio::null())
.spawn()?
.wait()?;
}
}
Ok(())
}
fn initialize_server(action: OptActionWithServer) -> Result<()> {
if action.needs_server_running() {
println!("No eww server running"); println!("No eww server running");
return Ok(()); return Ok(());
} }
@ -205,8 +243,8 @@ fn initialize_server(opts: Opt) -> Result<()> {
} }
// run the command that eww was started with // run the command that eww was started with
log::info!("running command: {:?}", &opts.action); log::info!("running command: {:?}", &action);
let (command, maybe_response_recv) = opts.action.into_eww_command(); let (command, maybe_response_recv) = action.into_eww_command();
app.handle_command(command); app.handle_command(command);
if let Some(response_recv) = maybe_response_recv { if let Some(response_recv) = maybe_response_recv {
if let Ok(response) = response_recv.recv_timeout(std::time::Duration::from_millis(100)) { if let Ok(response) = response_recv.recv_timeout(std::time::Duration::from_millis(100)) {
@ -235,9 +273,9 @@ fn run_server_thread(evt_send: glib::Sender<app::EwwCommand>) -> Result<()> {
for stream in listener.incoming() { for stream in listener.incoming() {
try_logging_errors!("handling message from IPC client" => { try_logging_errors!("handling message from IPC client" => {
let mut stream = stream?; let mut stream = stream?;
let opts: Opt = bincode::deserialize_from(&stream)?; let action: OptActionWithServer = bincode::deserialize_from(&stream)?;
log::info!("received command from IPC: {:?}", &opts); log::info!("received command from IPC: {:?}", &action);
let (command, maybe_response_recv) = opts.action.into_eww_command(); let (command, maybe_response_recv) = action.into_eww_command();
evt_send.send(command)?; evt_send.send(command)?;
if let Some(response_recv) = maybe_response_recv { if let Some(response_recv) = maybe_response_recv {
if let Ok(response) = response_recv.recv_timeout(std::time::Duration::from_millis(100)) { if let Ok(response) = response_recv.recv_timeout(std::time::Duration::from_millis(100)) {
@ -295,8 +333,6 @@ fn do_detach() -> Result<()> {
nix::unistd::ForkResult::Child => {} nix::unistd::ForkResult::Child => {}
} }
nix::unistd::setsid().context("Failed to run setsid")?;
let file = std::fs::OpenOptions::new() let file = std::fs::OpenOptions::new()
.create(true) .create(true)
.append(true) .append(true)
@ -313,6 +349,8 @@ fn do_detach() -> Result<()> {
if nix::unistd::isatty(2)? { if nix::unistd::isatty(2)? {
nix::unistd::dup2(std::io::stderr().as_raw_fd(), fd)?; nix::unistd::dup2(std::io::stderr().as_raw_fd(), fd)?;
} }
nix::unistd::setsid().context("Failed to run setsid")?;
Ok(()) Ok(())
} }

View file

@ -219,7 +219,7 @@ fn build_gtk_scale(bargs: &mut BuilderArgs) -> Result<gtk::Scale> {
} }
/// @widget input /// @widget input
/// @desc an input field that doesn't yet really work /// @desc an input field. For this to be useful, set `focusable="true"` on the window.
fn build_gtk_input(bargs: &mut BuilderArgs) -> Result<gtk::Entry> { fn build_gtk_input(bargs: &mut BuilderArgs) -> Result<gtk::Entry> {
let gtk_widget = gtk::Entry::new(); let gtk_widget = gtk::Entry::new();
let on_change_handler_id: Rc<RefCell<Option<glib::SignalHandlerId>>> = Rc::new(RefCell::new(None)); let on_change_handler_id: Rc<RefCell<Option<glib::SignalHandlerId>>> = Rc::new(RefCell::new(None));