diff --git a/Cargo.lock b/Cargo.lock
index 1c17b12..5fed2e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -9,6 +9,15 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "anyhow"
version = "1.0.38"
@@ -27,6 +36,17 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
[[package]]
name = "autocfg"
version = "1.0.1"
@@ -93,6 +113,21 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "clap"
+version = "2.33.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags 1.2.1",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
[[package]]
name = "const_fn"
version = "0.4.5"
@@ -250,6 +285,8 @@ dependencies = [
name = "espanso"
version = "1.0.0"
dependencies = [
+ "anyhow",
+ "clap",
"espanso-clipboard",
"espanso-config",
"espanso-detect",
@@ -258,8 +295,11 @@ dependencies = [
"espanso-match",
"espanso-path",
"espanso-ui",
+ "lazy_static",
+ "log",
"maplit",
"simplelog",
+ "thiserror",
]
[[package]]
@@ -448,6 +488,15 @@ dependencies = [
"unicode-segmentation",
]
+[[package]]
+name = "hermit-abi"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "itertools"
version = "0.10.0"
@@ -867,6 +916,12 @@ dependencies = [
"termcolor",
]
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
[[package]]
name = "strum"
version = "0.8.0"
@@ -947,6 +1002,15 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
[[package]]
name = "thiserror"
version = "1.0.23"
@@ -993,6 +1057,12 @@ version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
+[[package]]
+name = "unicode-width"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
+
[[package]]
name = "unicode-xid"
version = "0.0.4"
@@ -1005,6 +1075,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
[[package]]
name = "version_check"
version = "0.9.2"
diff --git a/espanso/Cargo.toml b/espanso/Cargo.toml
index 4843267..f6a2412 100644
--- a/espanso/Cargo.toml
+++ b/espanso/Cargo.toml
@@ -23,4 +23,9 @@ espanso-clipboard = { path = "../espanso-clipboard" }
espanso-info = { path = "../espanso-info" }
espanso-path = { path = "../espanso-path" }
maplit = "1.0.2"
-simplelog = "0.9.0"
\ No newline at end of file
+simplelog = "0.9.0"
+log = "0.4.14"
+anyhow = "1.0.38"
+thiserror = "1.0.23"
+clap = "2.33.3"
+lazy_static = "1.4.0"
\ No newline at end of file
diff --git a/espanso/src/cli/mod.rs b/espanso/src/cli/mod.rs
new file mode 100644
index 0000000..df2cb10
--- /dev/null
+++ b/espanso/src/cli/mod.rs
@@ -0,0 +1,65 @@
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2019-2021 Federico Terzi
+ *
+ * espanso is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * espanso is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with espanso. If not, see .
+ */
+
+use clap::ArgMatches;
+use espanso_config::{config::ConfigStore, matches::store::MatchStore};
+use espanso_path::Paths;
+
+pub mod log;
+pub mod path;
+
+pub struct CliModule {
+ pub enable_logs: bool,
+ pub requires_paths: bool,
+ pub requires_config: bool,
+ pub subcommand: String,
+ pub entry: fn(CliModuleArgs),
+}
+
+impl Default for CliModule {
+ fn default() -> Self {
+ Self {
+ enable_logs: false,
+ requires_paths: false,
+ requires_config: false,
+ subcommand: "".to_string(),
+ entry: |_| {},
+ }
+ }
+}
+
+pub struct CliModuleArgs {
+ pub config_store: Option>,
+ pub match_store: Option>,
+ pub is_legacy_config: bool,
+ pub paths: Option,
+ pub cli_args: Option>,
+}
+
+impl Default for CliModuleArgs {
+ fn default() -> Self {
+ Self {
+ config_store: None,
+ match_store: None,
+ is_legacy_config: false,
+ paths: None,
+ cli_args: None,
+ }
+ }
+}
diff --git a/espanso/src/cli/path.rs b/espanso/src/cli/path.rs
new file mode 100644
index 0000000..e5a276b
--- /dev/null
+++ b/espanso/src/cli/path.rs
@@ -0,0 +1,59 @@
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2019-2021 Federico Terzi
+ *
+ * espanso is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * espanso is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with espanso. If not, see .
+ */
+
+use super::{CliModule, CliModuleArgs};
+
+pub fn new() -> CliModule {
+ CliModule {
+ requires_paths: true,
+ requires_config: true,
+ subcommand: "path".to_string(),
+ entry: path_main,
+ ..Default::default()
+ }
+}
+
+fn path_main(args: CliModuleArgs) {
+ let paths = args.paths.expect("missing paths argument");
+ let cli_args = args.cli_args.expect("missing cli_args argument");
+
+ if cli_args.subcommand_matches("config").is_some() {
+ println!("{}", paths.config.to_string_lossy());
+ } else if cli_args.subcommand_matches("packages").is_some() {
+ println!("{}", paths.packages.to_string_lossy());
+ } else if cli_args.subcommand_matches("data").is_some() || cli_args.subcommand_matches("runtime").is_some() {
+ println!("{}", paths.runtime.to_string_lossy());
+ } else if cli_args.subcommand_matches("default").is_some() {
+ if args.is_legacy_config {
+ println!("{}", paths.config.join("default.yml").to_string_lossy());
+ } else {
+ println!("{}", paths.config.join("config").join("default.yml").to_string_lossy());
+ }
+ } else if cli_args.subcommand_matches("base").is_some() {
+ if args.is_legacy_config {
+ eprintln!("base config not available when using legacy configuration format");
+ } else {
+ println!("{}", paths.config.join("match").join("base.yml").to_string_lossy());
+ }
+ } else {
+ println!("Config: {}", paths.config.to_string_lossy());
+ println!("Packages: {}", paths.packages.to_string_lossy());
+ println!("Runtime: {}", paths.runtime.to_string_lossy());
+ }
+}
diff --git a/espanso/src/logging/mod.rs b/espanso/src/logging/mod.rs
new file mode 100644
index 0000000..ff3c52d
--- /dev/null
+++ b/espanso/src/logging/mod.rs
@@ -0,0 +1,89 @@
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2019-2021 Federico Terzi
+ *
+ * espanso is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * espanso is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with espanso. If not, see .
+ */
+
+use anyhow::Result;
+use std::{
+ fs::{File, OpenOptions},
+ path::Path,
+};
+use std::{
+ io::Write,
+ sync::{Arc, Mutex},
+};
+
+/// This struct can be passed as an output to the logger to "defer" the
+/// decision of the output file
+#[derive(Clone)]
+pub(crate) struct FileProxy {
+ output: Arc>>,
+}
+
+impl FileProxy {
+ pub fn new() -> Self {
+ Self {
+ output: Arc::new(Mutex::new(None)),
+ }
+ }
+
+ pub fn set_output_file(&self, path: &Path) -> Result<()> {
+ let log_file = OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(true)
+ .append(true)
+ .open(path)?;
+ let mut lock = self.output.lock().expect("unable to obtain FileProxy lock");
+ *lock = Some(log_file);
+ Ok(())
+ }
+}
+
+impl Write for FileProxy {
+ fn write(&mut self, buf: &[u8]) -> std::io::Result {
+ match self.output.lock() {
+ Ok(lock) => {
+ if let Some(mut output) = lock.as_ref() {
+ output.write(buf)
+ } else {
+ Ok(0)
+ }
+ }
+ Err(_) => Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "lock poison error",
+ )),
+ }
+ }
+
+ fn flush(&mut self) -> std::io::Result<()> {
+ match self.output.lock() {
+ Ok(lock) => {
+ if let Some(mut output) = lock.as_ref() {
+ output.flush()
+ } else {
+ Ok(())
+ }
+ }
+ Err(_) => Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "lock poison error",
+ )),
+ }
+ }
+}
diff --git a/espanso/src/main.rs b/espanso/src/main.rs
index 7e8ccb9..cc5048c 100644
--- a/espanso/src/main.rs
+++ b/espanso/src/main.rs
@@ -1,144 +1,264 @@
-use std::{path::PathBuf, time::Duration};
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2019-2021 Federico Terzi
+ *
+ * espanso is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * espanso is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with espanso. If not, see .
+ */
-use espanso_detect::{
- event::{InputEvent, Status},
- get_source,
- hotkey::HotKey,
- SourceCreationOptions,
-};
-use espanso_inject::{get_injector, keys, Injector};
-use espanso_ui::{event::UIEvent::*, icons::TrayIcon, menu::*};
-use simplelog::{CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode};
+#[macro_use]
+extern crate lazy_static;
+
+use clap::{App, AppSettings, Arg, SubCommand};
+use cli::{CliModule, CliModuleArgs};
+use logging::FileProxy;
+use simplelog::{CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger};
+
+mod cli;
+mod engine;
+mod logging;
+mod util;
+
+const VERSION: &str = env!("CARGO_PKG_VERSION");
+const LOG_FILE_NAME: &str = "espanso.log";
+
+lazy_static! {
+ static ref CLI_HANDLERS: Vec = vec![
+ cli::path::new(),
+ ];
+}
fn main() {
- println!("Hello, world!z");
+ // TODO: attach console
- CombinedLogger::init(vec![
- TermLogger::new(LevelFilter::Debug, Config::default(), TerminalMode::Mixed),
- // WriteLogger::new(
- // LevelFilter::Info,
- // Config::default(),
- // File::create("my_rust_binary.log").unwrap(),
- // ),
- ])
- .unwrap();
-
- let paths = espanso_path::resolve_paths();
- println!("paths: {:?}", paths);
- let config = espanso_config::load_legacy(&paths.config, &paths.packages).unwrap();
+ let install_subcommand = SubCommand::with_name("install")
+ .about("Install a package. Equivalent to 'espanso package install'")
+ .arg(
+ Arg::with_name("external")
+ .short("e")
+ .long("external")
+ .required(false)
+ .takes_value(false)
+ .help("Allow installing packages from non-verified repositories."),
+ )
+ .arg(Arg::with_name("package_name").help("Package name"))
+ .arg(
+ Arg::with_name("repository_url")
+ .help("(Optional) Link to GitHub repository")
+ .required(false)
+ .default_value("hub"),
+ )
+ .arg(
+ Arg::with_name("proxy")
+ .help("Use a proxy, should be used as --proxy=https://proxy:1234")
+ .required(false)
+ .long("proxy")
+ .takes_value(true),
+ );
- // let icon_paths = vec![
- // (
- // espanso_ui::icons::TrayIcon::Normal,
- // r"C:\Users\Freddy\AppData\Local\espanso\espanso.ico".to_string(),
- // ),
- // (
- // espanso_ui::icons::TrayIcon::Disabled,
- // r"C:\Users\Freddy\AppData\Local\espanso\espansored.ico".to_string(),
- // ),
- // ];
- let icon_paths = vec![
- (
- espanso_ui::icons::TrayIcon::Normal,
- r"/Users/freddy/Library/Application Support/espanso/icon.png".to_string(),
- ),
- (
- espanso_ui::icons::TrayIcon::Disabled,
- r"/Users/freddy/Library/Application Support/espanso/icondisabled.png".to_string(),
- ),
- ];
+ let uninstall_subcommand = SubCommand::with_name("uninstall")
+ .about("Remove an installed package. Equivalent to 'espanso package uninstall'")
+ .arg(Arg::with_name("package_name").help("Package name"));
- // let (remote, mut eventloop) = espanso_ui::win32::create(espanso_ui::win32::Win32UIOptions {
- // show_icon: true,
- // icon_paths: &icon_paths,
- // notification_icon_path: r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png"
- // .to_string(),
- // });
- // let (remote, mut eventloop) = espanso_ui::mac::create(espanso_ui::mac::MacUIOptions {
- // show_icon: true,
- // icon_paths: &icon_paths,
- // });
- let (remote, mut eventloop) = espanso_ui::create_ui(espanso_ui::UIOptions {
- notification_icon_path: Some(
- r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png".to_string(),
- ),
- ..Default::default()
- })
- .unwrap();
+ let mut clap_instance = App::new("espanso")
+ .version(VERSION)
+ .author("Federico Terzi")
+ .about("A Privacy-first, Cross-platform Text Expander")
+ .arg(Arg::with_name("v")
+ .short("v")
+ .multiple(true)
+ .help("Sets the level of verbosity"))
+ .subcommand(SubCommand::with_name("cmd")
+ .about("Send a command to the espanso daemon.")
+ .subcommand(SubCommand::with_name("exit")
+ .about("Terminate the daemon."))
+ .subcommand(SubCommand::with_name("enable")
+ .about("Enable the espanso replacement engine."))
+ .subcommand(SubCommand::with_name("disable")
+ .about("Disable the espanso replacement engine."))
+ .subcommand(SubCommand::with_name("toggle")
+ .about("Toggle the status of the espanso replacement engine."))
+ )
+ .subcommand(SubCommand::with_name("edit")
+ .about("Open the default text editor to edit config files and reload them automatically when exiting")
+ .arg(Arg::with_name("config")
+ .help("Defaults to \"default\". The configuration file name to edit (without the .yml extension)."))
+ .arg(Arg::with_name("norestart")
+ .short("n")
+ .long("norestart")
+ .required(false)
+ .takes_value(false)
+ .help("Avoid restarting espanso after editing the file"))
+ )
+ .subcommand(SubCommand::with_name("detect")
+ .about("Tool to detect current window properties, to simplify filters creation."))
+ .subcommand(SubCommand::with_name("daemon")
+ .about("Start the daemon without spawning a new process."))
+ .subcommand(SubCommand::with_name("register")
+ .about("MacOS and Linux only. Register espanso in the system daemon manager."))
+ .subcommand(SubCommand::with_name("unregister")
+ .about("MacOS and Linux only. Unregister espanso from the system daemon manager."))
+ .subcommand(SubCommand::with_name("log")
+ .about("Print the latest daemon logs."))
+ .subcommand(SubCommand::with_name("start")
+ .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")
+ .about("Check if the espanso daemon is running or not."))
+ .subcommand(SubCommand::with_name("path")
+ .about("Prints all the espanso directory paths to easily locate configuration and matches.")
+ .subcommand(SubCommand::with_name("config")
+ .about("Print the current config folder path."))
+ .subcommand(SubCommand::with_name("packages")
+ .about("Print the current packages folder path."))
+ .subcommand(SubCommand::with_name("data")
+ .about("Print the current data folder path.")
+ .setting(AppSettings::Hidden)) // Legacy path
+ .subcommand(SubCommand::with_name("runtime")
+ .about("Print the current runtime folder path."))
+ .subcommand(SubCommand::with_name("default")
+ .about("Print the default configuration file path."))
+ .subcommand(SubCommand::with_name("base")
+ .about("Print the default match file path."))
+ )
+ .subcommand(SubCommand::with_name("match")
+ .about("List and execute matches from the CLI")
+ .subcommand(SubCommand::with_name("list")
+ .about("Print all matches to standard output")
+ .arg(Arg::with_name("json")
+ .short("j")
+ .long("json")
+ .help("Return the matches as json")
+ .required(false)
+ .takes_value(false)
+ )
+ .arg(Arg::with_name("onlytriggers")
+ .short("t")
+ .long("onlytriggers")
+ .help("Print only triggers without replacement")
+ .required(false)
+ .takes_value(false)
+ )
+ .arg(Arg::with_name("preservenewlines")
+ .short("n")
+ .long("preservenewlines")
+ .help("Preserve newlines when printing replacements")
+ .required(false)
+ .takes_value(false)
+ )
+ )
+ .subcommand(SubCommand::with_name("exec")
+ .about("Triggers the expansion of the given match")
+ .arg(Arg::with_name("trigger")
+ .help("The trigger of the match to be expanded")
+ )
+ )
+ )
+ // Package manager
+ .subcommand(SubCommand::with_name("package")
+ .about("Espanso package manager commands")
+ .subcommand(install_subcommand.clone())
+ .subcommand(uninstall_subcommand.clone())
+ .subcommand(SubCommand::with_name("list")
+ .about("List all installed packages")
+ .arg(Arg::with_name("full")
+ .help("Print all package info")
+ .long("full")))
- eventloop.initialize().unwrap();
+ .subcommand(SubCommand::with_name("refresh")
+ .about("Update espanso package index"))
+ )
+ .subcommand(SubCommand::with_name("worker")
+ .setting(AppSettings::Hidden)
+ .arg(Arg::with_name("reload")
+ .short("r")
+ .long("reload")
+ .required(false)
+ .takes_value(false))
+ )
+ .subcommand(install_subcommand)
+ .subcommand(uninstall_subcommand);
- let handle = std::thread::spawn(move || {
- let injector = get_injector(Default::default()).unwrap();
- let mut source = get_source(SourceCreationOptions {
- //use_evdev: true,
- hotkeys: vec![
- HotKey::new(1, "CTRL+SPACE").unwrap(),
- //HotKey::new(1, "OPTION+SPACE").unwrap(),
- HotKey::new(2, "CTRL+OPTION+3").unwrap(),
- ],
- ..Default::default()
- })
- .unwrap();
- let clipboard = espanso_clipboard::get_clipboard(Default::default()).unwrap();
- let provider = espanso_info::get_provider().unwrap();
- source.initialize().unwrap();
- source
- .eventloop(Box::new(move |event: InputEvent| {
- println!("ev {:?}", event);
- match event {
- InputEvent::Mouse(_) => {}
- InputEvent::Keyboard(evt) => {
- if evt.key == espanso_detect::event::Key::Escape && evt.status == Status::Released {
- //remote.update_tray_icon(espanso_ui::icons::TrayIcon::Disabled);
- //remote.show_notification("Espanso is running!");
- injector
- .send_string("Hey guys! @", Default::default())
- .expect("error");
- //std::thread::sleep(std::time::Duration::from_secs(2));
- //injector.send_key_combination(&[keys::Key::Control, keys::Key::V], Default::default()).unwrap();
- }
- if evt.key == espanso_detect::event::Key::Shift && evt.status == Status::Released {
- println!("info {:?}", provider.get_info());
- }
- }
- InputEvent::HotKey(hotkey) => {
- if hotkey.hotkey_id == 2 {
- println!("clip {:?}", clipboard.get_text());
- } else if hotkey.hotkey_id == 1 {
- //clipboard.set_text("test text").unwrap();
- clipboard.set_html("test text", Some("test text fallback")).unwrap();
- //clipboard.set_image(&PathBuf::from(r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreen.png")).unwrap();
- }
- }
- }
- }))
- .unwrap();
- });
+ // TODO: explain that the start and restart commands are only meaningful
+ // when using the system daemon manager on macOS and Linux
- eventloop.run(Box::new(move |event| {
- println!("ui {:?}", event);
- let menu = Menu::from(vec![
- MenuItem::Simple(SimpleMenuItem::new("open", "Open")),
- MenuItem::Separator,
- MenuItem::Sub(SubMenuItem::new(
- "Sub",
- vec![
- MenuItem::Simple(SimpleMenuItem::new("sub1", "Sub 1")),
- MenuItem::Simple(SimpleMenuItem::new("sub2", "Sub 2")),
- ],
- )),
- ])
- .unwrap();
- match event {
- TrayIconClick => {
- remote.show_context_menu(&menu);
- }
- ContextMenuClick(raw_id) => {
- //remote.update_tray_icon(TrayIcon::Disabled);
- remote.show_notification("Hello there!");
- println!("item {:?}", menu.get_item_id(raw_id));
- }
+ let matches = clap_instance.clone().get_matches();
+ let log_level = match matches.occurrences_of("v") {
+ 0 => LevelFilter::Warn,
+ 1 => LevelFilter::Info,
+ _ => LevelFilter::Debug,
+ };
+
+ let handler = CLI_HANDLERS
+ .iter()
+ .find(|cli| matches.subcommand_matches(&cli.subcommand).is_some());
+
+ if let Some(handler) = handler {
+ let log_proxy = FileProxy::new();
+ if handler.enable_logs {
+ CombinedLogger::init(vec![
+ TermLogger::new(log_level, Config::default(), TerminalMode::Mixed),
+ WriteLogger::new(log_level, Config::default(), log_proxy.clone()),
+ ])
+ .expect("unable to initialize logs");
}
- }));
-}
+
+ let mut cli_args: CliModuleArgs = CliModuleArgs::default();
+
+ if handler.requires_paths || handler.requires_config {
+ // TODO: here take into account env variable and/or command line flag
+ let paths = espanso_path::resolve_paths();
+
+ if handler.requires_config {
+ let (config_store, match_store, is_legacy_config) =
+ if espanso_config::is_legacy_config(&paths.config) {
+ let (config_store, match_store) =
+ espanso_config::load_legacy(&paths.config, &paths.packages)
+ .expect("unable to load legacy config");
+ (config_store, match_store, true)
+ } else {
+ let (config_store, match_store) =
+ espanso_config::load(&paths.config).expect("unable to load config");
+ (config_store, match_store, false)
+ };
+
+ cli_args.is_legacy_config = is_legacy_config;
+ cli_args.config_store = Some(config_store);
+ cli_args.match_store = Some(match_store);
+ }
+
+ if handler.enable_logs {
+ log_proxy
+ .set_output_file(&paths.runtime.join(LOG_FILE_NAME))
+ .expect("unable to set up log output file");
+ }
+
+ cli_args.paths = Some(paths);
+ }
+
+ if let Some(args) = matches.subcommand_matches(&handler.subcommand) {
+ cli_args.cli_args = Some(args.clone());
+ }
+
+ (handler.entry)(cli_args)
+ } else {
+ clap_instance
+ .print_long_help()
+ .expect("unable to print help");
+ println!();
+ }
+}
\ No newline at end of file
diff --git a/espanso/src/main_old2.rs b/espanso/src/main_old2.rs
deleted file mode 100644
index e51724e..0000000
--- a/espanso/src/main_old2.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-use espanso_detect::event::{InputEvent, Status};
-use espanso_ui::{linux::LinuxUIOptions, menu::*};
-use simplelog::{CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode};
-
-fn main() {
- println!("Hello, world!z");
- CombinedLogger::init(vec![
- TermLogger::new(LevelFilter::Debug, Config::default(), TerminalMode::Mixed),
- // WriteLogger::new(
- // LevelFilter::Info,
- // Config::default(),
- // File::create("my_rust_binary.log").unwrap(),
- // ),
- ])
- .unwrap();
-
- let icon_paths = vec![
- (
- espanso_ui::icons::TrayIcon::Normal,
- r"C:\Users\Freddy\AppData\Local\espanso\espanso.ico".to_string(),
- ),
- (
- espanso_ui::icons::TrayIcon::Disabled,
- r"C:\Users\Freddy\AppData\Local\espanso\espansored.ico".to_string(),
- ),
- ];
-
-
- // let (remote, mut eventloop) = espanso_ui::win32::create(espanso_ui::win32::Win32UIOptions {
- // show_icon: true,
- // icon_paths: &icon_paths,
- // notification_icon_path: r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png"
- // .to_string(),
- // });
- let (remote, mut eventloop) = espanso_ui::linux::create(LinuxUIOptions {
- notification_icon_path: r"/home/freddy/insync/Development/Espanso/Images/icongreensmall.png".to_owned(),
- });
-
- let handle = std::thread::spawn(move || {
- //let mut source = espanso_detect::win32::Win32Source::new();
- let mut source = espanso_detect::evdev::EVDEVSource::new();
- source.initialize();
- source.eventloop(Box::new(move |event: InputEvent| {
- println!("ev {:?}", event);
- match event {
- InputEvent::Mouse(_) => {}
- InputEvent::Keyboard(evt) => {
- if evt.key == espanso_detect::event::Key::Shift && evt.status == Status::Pressed {
- //remote.update_tray_icon(espanso_ui::icons::TrayIcon::Disabled);
- remote.show_notification("Espanso is running!");
- }
- }
- }
- }));
- });
-
- // eventloop.initialize();
- // eventloop.run(Box::new(move |event| {
- // println!("ui {:?}", event);
- // let menu = Menu::from(vec![
- // MenuItem::Simple(SimpleMenuItem::new("open", "Open")),
- // MenuItem::Separator,
- // MenuItem::Sub(SubMenuItem::new(
- // "Sub",
- // vec![
- // MenuItem::Simple(SimpleMenuItem::new("sub1", "Sub 1")),
- // MenuItem::Simple(SimpleMenuItem::new("sub2", "Sub 2")),
- // ],
- // )),
- // ])
- // .unwrap();
- // remote.show_context_menu(&menu);
- // }))
- eventloop.run();
-}