parent
2b4835171a
commit
7a679c6395
|
@ -8,7 +8,7 @@ use std::io::Read;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::event::KeyModifier;
|
use crate::event::KeyModifier;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use log::{error, LevelFilter};
|
use log::{error};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::sync::mpsc;
|
|
||||||
use std::os::raw::{c_void};
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use crate::bridge::linux::*;
|
use crate::bridge::linux::*;
|
||||||
|
|
||||||
|
|
95
src/main.rs
95
src/main.rs
|
@ -8,7 +8,7 @@ use std::time::Duration;
|
||||||
|
|
||||||
use clap::{App, Arg, SubCommand, ArgMatches};
|
use clap::{App, Arg, SubCommand, ArgMatches};
|
||||||
use fs2::FileExt;
|
use fs2::FileExt;
|
||||||
use log::{error, info, LevelFilter};
|
use log::{error, info, warn, LevelFilter};
|
||||||
use simplelog::{CombinedLogger, SharedLogger, TerminalMode, TermLogger};
|
use simplelog::{CombinedLogger, SharedLogger, TerminalMode, TermLogger};
|
||||||
|
|
||||||
use crate::config::ConfigSet;
|
use crate::config::ConfigSet;
|
||||||
|
@ -69,6 +69,10 @@ fn main() {
|
||||||
.about("Start the daemon without spawning a new process."))
|
.about("Start the daemon without spawning a new process."))
|
||||||
.subcommand(SubCommand::with_name("start")
|
.subcommand(SubCommand::with_name("start")
|
||||||
.about("Start the daemon spawning a new process in the background."))
|
.about("Start the daemon spawning a new process in the background."))
|
||||||
|
.subcommand(SubCommand::with_name("stop")
|
||||||
|
.about("Stop the espanso daemon."))
|
||||||
|
.subcommand(SubCommand::with_name("restart")
|
||||||
|
.about("Restart the espanso daemon."))
|
||||||
.subcommand(SubCommand::with_name("status")
|
.subcommand(SubCommand::with_name("status")
|
||||||
.about("Check if the espanso daemon is running or not."))
|
.about("Check if the espanso daemon is running or not."))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
@ -98,33 +102,43 @@ fn main() {
|
||||||
|
|
||||||
// Match the correct subcommand
|
// Match the correct subcommand
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("dump") {
|
if let Some(matches) = matches.subcommand_matches("cmd") {
|
||||||
|
cmd_main(config_set, matches);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(_) = matches.subcommand_matches("dump") {
|
||||||
println!("{:#?}", config_set);
|
println!("{:#?}", config_set);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("detect") {
|
if let Some(_) = matches.subcommand_matches("detect") {
|
||||||
detect_main();
|
detect_main();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("daemon") {
|
if let Some(_) = matches.subcommand_matches("daemon") {
|
||||||
daemon_main(config_set);
|
daemon_main(config_set);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("start") {
|
if let Some(_) = matches.subcommand_matches("start") {
|
||||||
start_main(config_set);
|
start_main(config_set);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("status") {
|
if let Some(_) = matches.subcommand_matches("status") {
|
||||||
status_main();
|
status_main();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("cmd") {
|
if let Some(_) = matches.subcommand_matches("stop") {
|
||||||
cmd_main(matches);
|
stop_main(config_set);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(_) = matches.subcommand_matches("restart") {
|
||||||
|
restart_main(config_set);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,6 +269,49 @@ fn status_main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Stop subcommand, used to stop the daemon.
|
||||||
|
fn stop_main(config_set: ConfigSet) {
|
||||||
|
// Try to acquire lock file
|
||||||
|
let lock_file = acquire_lock();
|
||||||
|
if lock_file.is_some() {
|
||||||
|
println!("espanso daemon is not running.");
|
||||||
|
release_lock(lock_file.unwrap());
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = send_command(config_set, IPCCommand{
|
||||||
|
id: "exit".to_owned(),
|
||||||
|
payload: "".to_owned(),
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Err(e) = res {
|
||||||
|
println!("{}", e);
|
||||||
|
exit(1);
|
||||||
|
}else{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restart_main(config_set: ConfigSet) {
|
||||||
|
// Kill the daemon if running
|
||||||
|
let lock_file = acquire_lock();
|
||||||
|
if lock_file.is_none() {
|
||||||
|
// Terminate the current espanso daemon
|
||||||
|
send_command(config_set.clone(), IPCCommand{
|
||||||
|
id: "exit".to_owned(),
|
||||||
|
payload: "".to_owned(),
|
||||||
|
}).unwrap_or_else(|e| warn!("Unable to send IPC command to daemon: {}", e));
|
||||||
|
}else{
|
||||||
|
release_lock(lock_file.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread::sleep(Duration::from_millis(300));
|
||||||
|
|
||||||
|
// Restart the daemon
|
||||||
|
start_main(config_set);
|
||||||
|
}
|
||||||
|
|
||||||
/// Cli tool used to analyze active windows to extract useful information
|
/// Cli tool used to analyze active windows to extract useful information
|
||||||
/// to create configuration filters.
|
/// to create configuration filters.
|
||||||
fn detect_main() {
|
fn detect_main() {
|
||||||
|
@ -289,23 +346,23 @@ fn detect_main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmd_main(matches: &ArgMatches) {
|
fn cmd_main(config_set: ConfigSet, matches: &ArgMatches) {
|
||||||
let command = if let Some(matches) = matches.subcommand_matches("exit") {
|
let command = if let Some(_) = matches.subcommand_matches("exit") {
|
||||||
Some(IPCCommand {
|
Some(IPCCommand {
|
||||||
id: String::from("exit"),
|
id: String::from("exit"),
|
||||||
payload: String::from(""),
|
payload: String::from(""),
|
||||||
})
|
})
|
||||||
}else if let Some(matches) = matches.subcommand_matches("toggle") {
|
}else if let Some(_) = matches.subcommand_matches("toggle") {
|
||||||
Some(IPCCommand {
|
Some(IPCCommand {
|
||||||
id: String::from("toggle"),
|
id: String::from("toggle"),
|
||||||
payload: String::from(""),
|
payload: String::from(""),
|
||||||
})
|
})
|
||||||
}else if let Some(matches) = matches.subcommand_matches("enable") {
|
}else if let Some(_) = matches.subcommand_matches("enable") {
|
||||||
Some(IPCCommand {
|
Some(IPCCommand {
|
||||||
id: String::from("enable"),
|
id: String::from("enable"),
|
||||||
payload: String::from(""),
|
payload: String::from(""),
|
||||||
})
|
})
|
||||||
}else if let Some(matches) = matches.subcommand_matches("disable") {
|
}else if let Some(_) = matches.subcommand_matches("disable") {
|
||||||
Some(IPCCommand {
|
Some(IPCCommand {
|
||||||
id: String::from("disable"),
|
id: String::from("disable"),
|
||||||
payload: String::from(""),
|
payload: String::from(""),
|
||||||
|
@ -315,15 +372,23 @@ fn cmd_main(matches: &ArgMatches) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(command) = command {
|
if let Some(command) = command {
|
||||||
let ipc_client = protocol::get_ipc_client();
|
let res = send_command(config_set, command);
|
||||||
ipc_client.send_command(command);
|
|
||||||
|
|
||||||
|
if res.is_ok() {
|
||||||
exit(0);
|
exit(0);
|
||||||
|
}else{
|
||||||
|
println!("{}", res.unwrap_err());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_command(config_set: ConfigSet, command: IPCCommand) -> Result<(), String> {
|
||||||
|
let ipc_client = protocol::get_ipc_client();
|
||||||
|
ipc_client.send_command(command)
|
||||||
|
}
|
||||||
|
|
||||||
fn acquire_lock() -> Option<File> {
|
fn acquire_lock() -> Option<File> {
|
||||||
let espanso_dir = context::get_data_dir();
|
let espanso_dir = context::get_data_dir();
|
||||||
let lock_file_path = espanso_dir.join("espanso.lock");
|
let lock_file_path = espanso_dir.join("espanso.lock");
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Result;
|
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
use crate::event::Event;
|
use crate::event::Event;
|
||||||
use crate::event::Event::*;
|
|
||||||
use crate::event::ActionType;
|
use crate::event::ActionType;
|
||||||
use crate::event::ActionType::*;
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
mod windows;
|
mod windows;
|
||||||
|
@ -17,7 +14,7 @@ pub trait IPCServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IPCClient {
|
pub trait IPCClient {
|
||||||
fn send_command(&self, command: IPCCommand);
|
fn send_command(&self, command: IPCCommand) -> Result<(), String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
use std::io::{BufRead, BufReader, Read};
|
use std::io::{BufReader, Read};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::unix::net::{UnixStream,UnixListener};
|
use std::os::unix::net::{UnixStream,UnixListener};
|
||||||
use std::thread;
|
use log::{info, error, warn};
|
||||||
use log::{info, error};
|
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
use super::IPCCommand;
|
use super::IPCCommand;
|
||||||
|
|
||||||
use crate::context;
|
use crate::context;
|
||||||
use crate::context::get_data_dir;
|
|
||||||
use crate::event::*;
|
use crate::event::*;
|
||||||
|
|
||||||
const UNIX_SOCKET_NAME : &str = "espanso.sock";
|
const UNIX_SOCKET_NAME : &str = "espanso.sock";
|
||||||
|
@ -29,7 +27,9 @@ impl super::IPCServer for UnixIPCServer {
|
||||||
let espanso_dir = context::get_data_dir();
|
let espanso_dir = context::get_data_dir();
|
||||||
let unix_socket = espanso_dir.join(UNIX_SOCKET_NAME);
|
let unix_socket = espanso_dir.join(UNIX_SOCKET_NAME);
|
||||||
|
|
||||||
std::fs::remove_file(unix_socket.clone());
|
std::fs::remove_file(unix_socket.clone()).unwrap_or_else(|e| {
|
||||||
|
warn!("Unable to delete Unix socket: {}", e);
|
||||||
|
});
|
||||||
let listener = UnixListener::bind(unix_socket.clone()).expect("Can't bind to Unix Socket");
|
let listener = UnixListener::bind(unix_socket.clone()).expect("Can't bind to Unix Socket");
|
||||||
|
|
||||||
info!("Binded to IPC unix socket: {}", unix_socket.as_path().display());
|
info!("Binded to IPC unix socket: {}", unix_socket.as_path().display());
|
||||||
|
@ -39,8 +39,9 @@ impl super::IPCServer for UnixIPCServer {
|
||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
let mut json_str= String::new();
|
let mut json_str= String::new();
|
||||||
let mut buf_reader = BufReader::new(stream);
|
let mut buf_reader = BufReader::new(stream);
|
||||||
buf_reader.read_to_string(&mut json_str);
|
let res = buf_reader.read_to_string(&mut json_str);
|
||||||
|
|
||||||
|
if res.is_ok() {
|
||||||
let command : Result<IPCCommand, serde_json::Error> = serde_json::from_str(&json_str);
|
let command : Result<IPCCommand, serde_json::Error> = serde_json::from_str(&json_str);
|
||||||
match command {
|
match command {
|
||||||
Ok(command) => {
|
Ok(command) => {
|
||||||
|
@ -54,6 +55,7 @@ impl super::IPCServer for UnixIPCServer {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("Error: {}", err);
|
println!("Error: {}", err);
|
||||||
break;
|
break;
|
||||||
|
@ -75,24 +77,27 @@ impl UnixIPCClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::IPCClient for UnixIPCClient {
|
impl super::IPCClient for UnixIPCClient {
|
||||||
fn send_command(&self, command: IPCCommand) {
|
fn send_command(&self, command: IPCCommand) -> Result<(), String> {
|
||||||
let espanso_dir = context::get_data_dir();
|
let espanso_dir = context::get_data_dir();
|
||||||
let unix_socket = espanso_dir.join(UNIX_SOCKET_NAME);
|
let unix_socket = espanso_dir.join(UNIX_SOCKET_NAME);
|
||||||
|
|
||||||
// Open the stream
|
// Open the stream
|
||||||
let mut stream = UnixStream::connect(unix_socket);
|
let stream = UnixStream::connect(unix_socket);
|
||||||
match stream {
|
match stream {
|
||||||
Ok(mut stream) => {
|
Ok(mut stream) => {
|
||||||
let json_str = serde_json::to_string(&command);
|
let json_str = serde_json::to_string(&command);
|
||||||
if let Ok(json_str) = json_str {
|
if let Ok(json_str) = json_str {
|
||||||
stream.write_all(json_str.as_bytes()).unwrap_or_else(|e| {
|
stream.write_all(json_str.as_bytes()).unwrap_or_else(|e| {
|
||||||
println!("Can't write to IPC socket");
|
println!("Can't write to IPC socket: {}", e);
|
||||||
});
|
});
|
||||||
|
return Ok(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Can't connect to daemon: {}", e);
|
return Err(format!("Can't connect to daemon: {}", e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Err("Can't send command".to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,8 +14,8 @@ impl super::UIManager for LinuxUIManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_menu(&self, menu: Vec<MenuItem>) {
|
fn show_menu(&self, _menu: Vec<MenuItem>) {
|
||||||
unimplemented!()
|
// Not implemented on linux
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user