cargo-mate 1.7.5

Rust development companion that enhances cargo with intelligent workflows, state management, performance optimization, and comprehensive project monitoring.
Documentation
use serde::{Deserialize, Serialize};
use std::fmt;
use std::process::Command;
use anyhow::{Context, Result};
use colored::*;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ParsedError {
    pub code: String,
    pub file: String,
    pub line: usize,
    pub message: String,
}
impl fmt::Display for ParsedError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[{}] {}:{} - {}", self.code, self.file, self.line, self.message)
    }
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ParsedWarning {
    pub code: String,
    pub file: String,
    pub line: usize,
    pub message: String,
}
impl fmt::Display for ParsedWarning {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[{}] {}:{} - {}", self.code, self.file, self.line, self.message)
    }
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(untagged)]
pub enum MessageData {
    CompilerMessage(CompilerMessage),
    BuildScriptExecuted(BuildScriptExecuted),
    CompilerArtifact(CompilerArtifact),
    Other(serde_json::Value),
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct CompilerMessage {
    pub message: DiagnosticMessage,
    #[serde(default)]
    pub package_id: String,
    pub target: Option<Target>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct DiagnosticMessage {
    pub message: String,
    pub code: Option<DiagnosticCode>,
    pub level: String,
    pub spans: Vec<DiagnosticSpan>,
    pub children: Vec<DiagnosticMessage>,
    pub rendered: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct DiagnosticCode {
    pub code: String,
    pub explanation: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct DiagnosticSpan {
    pub file_name: String,
    pub line_start: usize,
    pub line_end: usize,
    pub column_start: usize,
    pub column_end: usize,
    pub text: Vec<SpanText>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct SpanText {
    pub text: String,
    pub highlight_start: usize,
    pub highlight_end: usize,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct BuildScriptExecuted {
    pub package_id: String,
    pub linked_libs: Vec<String>,
    pub linked_paths: Vec<String>,
    pub cfgs: Vec<String>,
    pub env: Vec<(String, String)>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct CompilerArtifact {
    pub package_id: String,
    pub target: Target,
    pub profile: ArtifactProfile,
    pub features: Vec<String>,
    pub filenames: Vec<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Target {
    pub name: String,
    pub kind: Vec<String>,
    pub src_path: String,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ArtifactProfile {
    pub opt_level: String,
    pub debuginfo: Option<u32>,
    pub test: bool,
}
pub fn parse_cargo_message(line: &str) -> Option<CargoMessage> {
    println!("🔍 {}", "Parsing cargo message requires captain binary".bright_blue());
    delegate_to_captain(vec!["parser", "parse", line])
        .ok()
        .and_then(|_| serde_json::from_str(line).ok())
}
pub fn format_error(msg: &DiagnosticMessage) -> ParsedError {
    println!("🔍 {}", "Formatting error requires captain binary".bright_blue());
    delegate_to_captain(vec!["parser", "format", "error", & msg.message]).ok();
    let code = msg
        .code
        .as_ref()
        .map(|c| c.code.clone())
        .unwrap_or_else(|| "unknown".to_string());
    let (file, line) = if !msg.spans.is_empty() {
        (msg.spans[0].file_name.clone(), msg.spans[0].line_start)
    } else {
        ("unknown".to_string(), 0)
    };
    ParsedError {
        code,
        file,
        line,
        message: msg.message.clone(),
    }
}
pub fn format_warning(msg: &DiagnosticMessage) -> ParsedWarning {
    println!("🔍 {}", "Formatting warning requires captain binary".bright_blue());
    delegate_to_captain(vec!["parser", "format", "warning", & msg.message]).ok();
    let code = msg
        .code
        .as_ref()
        .map(|c| c.code.clone())
        .unwrap_or_else(|| "unknown".to_string());
    let (file, line) = if !msg.spans.is_empty() {
        (msg.spans[0].file_name.clone(), msg.spans[0].line_start)
    } else {
        ("unknown".to_string(), 0)
    };
    ParsedWarning {
        code,
        file,
        line,
        message: msg.message.clone(),
    }
}
pub fn delegate_to_captain(args: Vec<&str>) -> Result<()> {
    let captain_path = match crate::captain::captain_status::find_captain_binary() {
        Some(path) => path,
        None => {
            println!("{}", "Advanced captain binary not found".red().bold());
            println!(
                "🔄 {}", "Auto-downloading captain binary from get.cargo.do/".cyan()
            );
            match crate::captain::captain_status::auto_download_captain() {
                Ok(path) => path,
                Err(e) => {
                    println!(
                        "{}", format!("Failed to download captain: {}", e) .red()
                    );
                    println!("💡 {}", "Please run: cm captain install".cyan());
                    println!("   Or upgrade at: https://cargo.do/pro");
                    println!();
                    println!(
                        "💡 {}", "Parser features require the captain binary:".cyan()
                    );
                    println!("   • Advanced cargo message parsing");
                    println!("   • Error and warning formatting");
                    println!("   • Compiler artifact analysis");
                    println!("   • Build script execution tracking");
                    return Ok(());
                }
            }
        }
    };
    let output = Command::new(&captain_path)
        .args(&args)
        .output()
        .context("Failed to execute captain binary for parsing")?;
    if !output.stdout.is_empty() {
        print!("{}", String::from_utf8_lossy(& output.stdout));
    }
    if !output.stderr.is_empty() {
        eprint!("{}", String::from_utf8_lossy(& output.stderr));
    }
    if !output.status.success() {
        println!(
            "{}", format!("Captain binary exited with status: {}", output.status)
            .red()
        );
    }
    Ok(())
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct CargoMessage {
    pub reason: String,
    #[serde(flatten)]
    pub data: MessageData,
}