kanri 0.10.2

Manage your projects within the terminal.
Documentation
use anyhow::{Result, anyhow, bail, ensure};
use std::{fs, io::Write};
use tempfile::NamedTempFile;

use crate::{
    cli::{TemplatesGetArgs, TemplatesListArgs, TemplatesNewArgs, TemplatesRemoveArgs},
    config::Config,
    platform,
    program::{LaunchOptions, launch_program},
    templates::Templates,
    terminal::{ask_dialog, print_done, print_title},
};

pub fn handle_new(args: TemplatesNewArgs) -> Result<()> {
    ensure!(args.name.is_some(), "Provide a name for template.");
    let name = args.name.unwrap();
    let mut file = NamedTempFile::new()?;
    writeln!(
        file,
        "# Write your command here. They will be added to template."
    )?;
    let file_path = file.path().to_str().unwrap();

    let config = Config::load(platform::config_file())?;
    let profile = config.get_profile(&config.options.current_profile)?;
    let launch_options = LaunchOptions {
        program: &profile.editor,
        args: vec![file_path.to_string()],
        cwd: None,
        fork_mode: profile.editor_fork_mode,
        quiet: false,
        env: None,
    };

    println!("The editor will launch with opened file.");
    launch_program(launch_options)?;

    let content = fs::read_to_string(file_path)?;
    let mut commands: Vec<String> = Vec::new();

    for line in content.lines() {
        if line.starts_with("#") {
            continue;
        }

        commands.push(line.to_string());
    }

    ensure!(!commands.is_empty(), "No commands entered.");

    println!("Creating template...");
    let templates_path = platform::templates_file();
    let mut templates = Templates::load(&templates_path)?;
    templates.add_template(&name, commands)?;
    if templates.save(templates_path).is_ok() {
        print_done("Template has been created.");
    } else {
        bail!("Failed to save templates.");
    }
    Ok(())
}

pub fn handle_list(args: TemplatesListArgs) -> Result<()> {
    let templates = Templates::load(platform::templates_file())?;
    if templates.is_empty() {
        println!("No templates found.");
        return Ok(());
    }

    if !args.pure {
        print_title("Templates");
    }

    for template in templates.list_templates().iter() {
        println!("{}{template}", if args.pure { "" } else { "  " })
    }
    Ok(())
}

pub fn handle_edit() -> Result<()> {
    let config_path = platform::config_file();
    let config = Config::load(&config_path)?;
    let profile = config.get_profile(&config.options.current_profile)?;
    let editor = profile.editor.clone();
    if editor.is_empty() {
        bail!("Editor program name is not set in the configuration file.");
    }

    let templates_path = platform::templates_file();
    let mut editor_args = profile.editor_args.clone();
    editor_args.push(templates_path.to_string_lossy().to_string());

    let launch_options = LaunchOptions {
        program: &editor,
        args: editor_args,
        fork_mode: false,
        quiet: false,
        cwd: None,
        env: None,
    };

    launch_program(launch_options).map_err(|e| anyhow!(e.to_string()))
}

pub fn handle_path() -> Result<()> {
    println!("{}", platform::templates_file().display());
    Ok(())
}

pub fn handle_get(args: TemplatesGetArgs) -> Result<()> {
    let templates = Templates::load(platform::templates_file())?;
    match templates.get_template(&args.name) {
        Some(template) => {
            if !args.pure {
                print_title("Commands of this template");
            }
            for command in template.iter() {
                println!("{}{command}", if args.pure { "" } else { "  " });
            }
        }
        None => {
            bail!("Template not found.");
        }
    }
    Ok(())
}

pub fn handle_clear() -> Result<()> {
    let templates_path = platform::templates_file();
    let mut templates = Templates::load(&templates_path)?;
    if ask_dialog("Clear all templates?", false, true) {
        templates.clear();
        templates.save(templates_path)?;
        print_done("Templates storage has been cleared.");
    } else {
        print_done("Aborted.");
    }
    Ok(())
}

pub fn handle_remove(args: TemplatesRemoveArgs) -> Result<()> {
    let templates_path = platform::templates_file();
    let mut templates = Templates::load(&templates_path)?;
    templates.remove_template(&args.name)?;
    templates.save(templates_path)?;
    print_done("Template has been removed.");
    Ok(())
}