use std::cmp::Ordering;
use std::env;
use std::fs;
pub fn find_gh() -> Option<std::path::PathBuf> {
if let Ok(path) = which::which("gh") {
Some(path)
} else if std::path::Path::new(r"C:\Program Files\GitHub CLI\gh.exe").exists() {
Some(std::path::PathBuf::from(
r"C:\Program Files\GitHub CLI\gh.exe",
))
} else {
None
}
}
pub fn find_ghci() -> Option<std::path::PathBuf> {
if let Ok(path) = which::which("ghci") {
Some(path)
} else if std::path::Path::new(r"C:\ghcup\bin\ghci.exe").exists() {
Some(std::path::PathBuf::from(r"C:\ghcup\bin\ghci.exe"))
} else {
None
}
}
pub fn find_supercollider() -> Option<std::path::PathBuf> {
if let Ok(path) = which::which("sclang") {
return Some(path);
}
let program_files =
std::env::var("ProgramFiles").unwrap_or_else(|_| r"C:\Program Files".to_string());
let sc_prefix = "SuperCollider-";
let mut latest_version: Option<(semver::Version, std::path::PathBuf)> = None;
if let Ok(entries) = fs::read_dir(&program_files) {
for entry in entries.flatten() {
let file_name = entry.file_name();
let file_name = file_name.to_string_lossy();
if let Some(version_str) = file_name.strip_prefix(sc_prefix) {
if let Ok(version) = semver::Version::parse(version_str) {
let exe_path = entry.path().join("sclang.exe");
if exe_path.exists() {
match &latest_version {
Some((latest, _)) if version.cmp(latest) == Ordering::Greater => {
latest_version = Some((version, exe_path));
}
None => {
latest_version = Some((version, exe_path));
}
_ => {}
}
}
}
}
}
}
latest_version.map(|(_, path)| path)
}
pub fn find_supercollider_scsynth() -> Option<std::path::PathBuf> {
if let Ok(path) = which::which("scsynth") {
return Some(path);
}
let program_files =
std::env::var("ProgramFiles").unwrap_or_else(|_| r"C:\Program Files".to_string());
let sc_prefix = "SuperCollider-";
let mut latest_version: Option<(semver::Version, std::path::PathBuf)> = None;
if let Ok(entries) = fs::read_dir(&program_files) {
for entry in entries.flatten() {
let file_name = entry.file_name();
let file_name = file_name.to_string_lossy();
if let Some(version_str) = file_name.strip_prefix(sc_prefix) {
if let Ok(version) = semver::Version::parse(version_str) {
let exe_path = entry.path().join("scsynth.exe");
if exe_path.exists() {
match &latest_version {
Some((latest, _)) if version.cmp(latest) == Ordering::Greater => {
latest_version = Some((version, exe_path));
}
None => {
latest_version = Some((version, exe_path));
}
_ => {}
}
}
}
}
}
}
latest_version.map(|(_, path)| path)
}
pub fn find_ghcup() -> Option<std::path::PathBuf> {
if let Ok(path) = which::which("ghcup") {
Some(path)
} else if std::path::Path::new(r"C:\ghcup\bin\ghcup.exe").exists() {
Some(std::path::PathBuf::from(r"C:\ghcup\bin\ghcup.exe"))
} else {
None
}
}
pub fn find_cabal() -> Option<std::path::PathBuf> {
if let Ok(path) = which::which("cabal") {
Some(path)
} else if std::path::Path::new(r"C:\ghcup\bin\cabal.exe").exists() {
Some(std::path::PathBuf::from(r"C:\ghcup\bin\cabal.exe"))
} else {
None
}
}
pub fn find_tools_set_env_path() {
if let Some(sc_path) = find_supercollider() {
if let Some(sc_dir) = sc_path.parent() {
let path_var = env::var_os("PATH").unwrap_or_default();
let paths_vec: Vec<std::path::PathBuf> = env::split_paths(&path_var).collect();
let sc_dir_str = sc_dir.to_string_lossy().to_lowercase();
let already_in_path = paths_vec
.iter()
.any(|p| p.to_string_lossy().to_lowercase() == sc_dir_str);
if !already_in_path {
let mut new_paths: Vec<std::path::PathBuf> = vec![sc_dir.to_path_buf()];
new_paths.extend(paths_vec);
let new_path = env::join_paths(new_paths).expect("Failed to join PATH");
unsafe {
env::set_var("PATH", &new_path);
}
}
}
}
}