snippy 0.1.3

A command-line tool for that makes using LLMs for code generation a breeze
Documentation
use crate::applier::utils::print_diff;
use crate::applier::Applier;
use crate::errors::ClipboardError;
use crate::extractor::ParsedBlock;
use crate::utils::{read_file_async, write_file_async};
use async_trait::async_trait;
use diffy::Patch;
use std::path::PathBuf;
use tracing::{debug, info};

pub struct DiffApplier {
    base_path: PathBuf,
}

impl DiffApplier {
    pub fn new(base_path: &PathBuf) -> Self {
        DiffApplier {
            base_path: base_path.clone(),
        }
    }
}

#[async_trait]
impl Applier for DiffApplier {
    async fn apply(&self, block: &ParsedBlock) -> Result<(), ClipboardError> {
        let file_path = self.base_path.join(&block.filename);
        debug!("Applying diff to file: {:?}", file_path);

        let original_content = read_file_async(&file_path).await.unwrap_or_default();
        let new_content = apply_diff(&file_path, &original_content, &block.content).await?;

        write_file_async(&file_path, &new_content).await?;

        info!("Applied diff to {:?}", file_path);
        print_diff(&block.filename, &original_content, &block.content);
        Ok(())
    }
}

pub async fn apply_diff(
    path: &PathBuf,
    current_content: &str,
    diff_content: &str,
) -> Result<String, ClipboardError> {
    let patch_result = Patch::from_str(diff_content);

    match patch_result {
        Ok(patch) => match diffy::apply(current_content, &patch) {
            Ok(new_content) => Ok(new_content),
            Err(e) => Err(ClipboardError::DiffError(format!(
                "Failed to apply diff for file {}: {}",
                path.display(),
                e.to_string()
            ))),
        },
        Err(e) => Err(ClipboardError::DiffError(format!(
            "Failed to parse diff for file {}: {}",
            path.display(),
            e.to_string()
        ))),
    }
}