hyprscratch 0.6.4

Improved scratchpad functionality for Hyprland
mod config;
mod daemon;
mod event;
mod extra;
mod logs;
mod scratchpad;
mod utils;

use crate::daemon::initialize_daemon;
use crate::extra::*;
use crate::logs::*;
use crate::utils::*;
use hyprland::error::HyprError;
use hyprland::Result;
use std::env::args;

const HYPRSCRATCH_DIR: &str = "/tmp/hyprscratch/";
const DEFAULT_LOGFILE: &str = "/tmp/hyprscratch/hyprscratch.log";
const DEFAULT_SOCKET: &str = "/tmp/hyprscratch/hyprscratch.sock";

const DEFAULT_CONFIG_FILES: [&str; 4] = [
    "hypr/hyprscratch.conf",
    "hyprscratch/config.conf",
    "hyprscratch/hyprscratch.conf",
    "hypr/hyprland.conf",
];

const KNOWN_CLI_COMMANDS: [&str; 7] = [
    "get-config",
    "version",
    "reload",
    "full",
    "help",
    "logs",
    "kill",
];

const KNOWN_COMMANDS: [&str; 19] = [
    "no-auto-reload",
    "get-config",
    "spotless",
    "hide-all",
    "kill-all",
    "previous",
    "version",
    "reload",
    "toggle",
    "clean",
    "eager",
    "cycle",
    "init",
    "show",
    "hide",
    "menu",
    "kill",
    "logs",
    "help",
];

fn exec_cli_command(command: &str, socket: Option<&str>, config: Option<String>) -> Result<()> {
    match command {
        "get-config" => print_config(socket, false),
        "kill" => send_request(socket, "kill", ""),
        "full" => print_full_raw(socket),
        "logs" => print_logs(false),
        "help" => Ok(print_help()),
        "version" => Ok(println!("hyprscratch v{}", env!("CARGO_PKG_VERSION"))),
        "reload" => send_request(socket, "reload", &config.unwrap_or_default()),
        _ => Ok(()),
    }
}

fn get_cli_command(args: &[String]) -> Option<&str> {
    for arg in args {
        if let Some(flag) = get_flag_name(arg) {
            return Some(flag);
        } else if arg.starts_with('-') {
            let _ = log(format!("Unknown flag: {arg}"), Warn);
        }
    }
    None
}

fn send_manual(args: &[String], socket: Option<&str>) -> Result<()> {
    if args.len() < 3 {
        let msg = format!(
            "Unknown command or not enough arguments for scratchpad in '{}'",
            args[1..].join(" ")
        );
        log(msg, Warn)?;
        return Ok(());
    }
    send_request(socket, "manual", &args[1..].join("^"))
}

fn exec_main_command(args: &[String], config: Option<String>, socket: Option<&str>) -> Result<()> {
    let get_arg = |i| args.get(i).map_or("", |x: &String| x.as_str());
    let (req, msg) = (get_arg(1), get_arg(2));
    match req {
        "init" => initialize_daemon(args.join(" "), config, socket),
        "menu" => menu(socket, msg, get_arg(3))?,
        "" => print_help(),
        _ if KNOWN_COMMANDS.contains(&req) => send_request(socket, req, msg)?,
        _ => send_manual(args, socket)?,
    }
    Ok(())
}

fn resolve_command(args: &[String], config: Option<String>, socket: Option<&str>) -> Result<()> {
    if let Some(cmd) = get_cli_command(args) {
        exec_cli_command(cmd, socket, config)?;
        return Ok(());
    }
    exec_main_command(args, config, socket)
}

fn hyprscratch(args: &[String]) -> Result<()> {
    let depracated_features = ["summon"];
    for feature in depracated_features {
        if args.contains(&feature.to_string()) {
            warn_deprecated(feature)?;
        }
    }

    let config = get_flag_arg(args, "config");
    let sock = get_flag_arg(args, "socket");
    let socket = sock.as_deref();
    resolve_command(args, config, socket)
}

fn catch_err(args: &[String], err: HyprError) {
    if let HyprError::IoError(e) = err {
        if e.to_string() == "Connection refused (os error 111)" {
            let _ = log("Could not connect to daemon. Is it running?".into(), Warn);
        }
    } else {
        {
            let _ = log(
                format!("{}, command: '{}'.", err, args[1..].join(" ")),
                Warn,
            );
        }
    }
}

fn main() {
    let args: Vec<String> = args().collect();
    hyprscratch(&args).unwrap_or_else(|e| catch_err(&args, e));
}