free-launch 0.2.8

A simple fuzzy launcher written in Rust.
Documentation
use serde::{Deserialize, Serialize};
use tracing::{error, info, warn};

use crate::free_launch::config::Config;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchProvider {
    pub name: String,
    pub aliases: Vec<String>,
    pub url: String,
    pub browser: Option<String>,
}

impl SearchProvider {
    /// Check if the given query matches any of this provider's aliases
    pub fn matches_alias(&self, query: &str) -> bool {
        self.aliases.iter().any(|alias| query.starts_with(alias))
    }

    /// Get the matching alias from the query, if any
    pub fn get_matching_alias(&self, query: &str) -> Option<&str> {
        // Get the first word from the query
        let first_word = query.split_whitespace().next()?;

        // Find the longest matching alias that equals the first word
        let mut best_match = "";
        for alias in &self.aliases {
            if first_word == alias && alias.len() > best_match.len() {
                best_match = alias;
            }
        }

        if best_match.is_empty() {
            None
        } else {
            Some(best_match)
        }
    }
}

pub(crate) fn load_search_providers() -> Vec<SearchProvider> {
    // Load search providers from config
    info!("Loading search providers from config...");
    // TODO load this in a separate thread
    // TODO pass in a reference to the config
    let search_providers = match Config::load() {
        Ok(Some(config)) => config.providers,
        // TODO just log the below
        Ok(None) => {
            warn!("No search config found at ~/.config/search/config.yaml");
            Vec::new()
        }
        Err(e) => {
            error!("Failed to load search config: {}", e);
            Vec::new()
        }
    };
    search_providers
}