use clap::Parser;
use std::path::PathBuf;
use crate::Result;
#[derive(Debug, Parser)]
#[clap(arg_required_else_help = true)]
pub struct Args {
command: String,
}
pub fn execute(args: Args, session: &scoop_rs::Session) -> Result<()> {
let config = session.config();
let shims_dir = PathBuf::from(config.root_path()).join("shims");
if !shims_dir.exists() {
eprintln!("Scoop shims directory not found: {}", shims_dir.display());
return Ok(());
}
let command = &args.command;
let candidates: Vec<PathBuf> = vec![
shims_dir.join(command),
shims_dir.join(format!("{}.exe", command)),
shims_dir.join(format!("{}.cmd", command)),
shims_dir.join(format!("{}.ps1", command)),
shims_dir.join(format!("{}.bat", command)),
shims_dir.join(format!("{}.sh", command)),
];
for candidate in candidates {
if candidate.exists() {
let content = std::fs::read_to_string(&candidate).unwrap_or_default();
let (app, target) = parse_shim(&content, &candidate);
match (&app, &target) {
(Some(app), Some(target)) => {
let display_target = if target.exists() {
target
.canonicalize()
.unwrap_or(target.clone())
.display()
.to_string()
} else {
target.display().to_string()
};
println!("{} -> {} ({})", command, display_target, app);
}
_ => {
let canonical = candidate.canonicalize().unwrap_or(candidate);
println!("{} -> {} (shim)", command, canonical.display());
}
}
return Ok(());
}
}
eprintln!("No shim found for command '{}'", command);
Ok(())
}
fn parse_shim(content: &str, _shim_path: &PathBuf) -> (Option<String>, Option<PathBuf>) {
for line in content.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with("@echo off") || line.starts_with("#!") {
continue;
}
if let Some(start) = line.find('"') {
if let Some(end) = line[start + 1..].find('"') {
let target = &line[start + 1..start + 1 + end];
let target_path = PathBuf::from(target);
if let Some(parent) = target_path.parent() {
if parent.file_name().and_then(|n| n.to_str()) == Some("current") {
if let Some(app) = parent
.parent()
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
{
return (Some(app.to_string()), Some(target_path));
}
}
if let Some(grandparent) = parent.parent() {
let dir_name = grandparent.file_name().and_then(|n| n.to_str());
if dir_name == Some("apps") {
if let Some(app_name) = parent.file_name().and_then(|n| n.to_str()) {
return (Some(app_name.to_string()), Some(target_path));
}
}
}
}
return (None, Some(target_path));
}
}
}
(None, None)
}