pub fn enable_ansi() {
#[cfg(target_os = "windows")]
{
let _ = colored::control::set_virtual_terminal(true);
}
}
fn supports_unicode() -> bool {
if !cfg!(target_os = "windows") {
return true;
}
std::env::var("WT_SESSION").is_ok() || std::env::var("TERM_PROGRAM").is_ok()
}
pub fn icon_ok() -> &'static str {
if supports_unicode() { "✓" } else { "+" }
}
pub fn icon_fail() -> &'static str {
if supports_unicode() { "✗" } else { "x" }
}
pub fn icon_play() -> &'static str {
if supports_unicode() { "▶" } else { ">" }
}
pub fn icon_info() -> &'static str {
if supports_unicode() { "ℹ" } else { "i" }
}
pub fn icon_dash() -> &'static str {
if supports_unicode() { "—" } else { "-" }
}
pub fn icon_warn() -> &'static str {
if supports_unicode() { "⚠" } else { "!" }
}
pub fn icon_eye() -> &'static str {
if supports_unicode() { "👁" } else { "*" }
}
pub fn is_windows() -> bool {
cfg!(target_os = "windows")
}
pub fn shell_exec(cmd: &str) -> std::io::Result<std::process::ExitStatus> {
if is_windows() {
std::process::Command::new("cmd")
.args(["/C", cmd])
.stdout(std::process::Stdio::inherit())
.stderr(std::process::Stdio::inherit())
.status()
} else {
std::process::Command::new("sh")
.args(["-c", cmd])
.stdout(std::process::Stdio::inherit())
.stderr(std::process::Stdio::inherit())
.status()
}
}
pub fn shell_output(cmd: &str) -> std::io::Result<std::process::Output> {
if is_windows() {
std::process::Command::new("cmd")
.args(["/C", cmd])
.output()
} else {
std::process::Command::new("sh")
.args(["-c", cmd])
.output()
}
}
pub fn python_cmd() -> &'static str {
if is_windows() {
"python"
} else if which::which("python3").is_ok() {
"python3"
} else {
"python"
}
}
pub fn find_available_port(start: u16, max_tries: u16) -> u16 {
for offset in 0..max_tries {
let port = start + offset;
if std::net::TcpListener::bind(("127.0.0.1", port)).is_ok() {
return port;
}
}
start
}
pub fn kill_port(port: u16) -> bool {
if std::net::TcpListener::bind(("127.0.0.1", port)).is_ok() {
return false; }
#[cfg(unix)]
{
let output = std::process::Command::new("lsof")
.args(["-ti", &format!("tcp:{}", port)])
.output();
if let Ok(output) = output {
let pids = String::from_utf8_lossy(&output.stdout);
for pid_str in pids.trim().lines() {
if let Ok(pid) = pid_str.trim().parse::<i32>() {
let our_pid = std::process::id() as i32;
if pid != our_pid {
unsafe {
libc::kill(pid, libc::SIGTERM);
}
}
}
}
std::thread::sleep(std::time::Duration::from_millis(500));
return std::net::TcpListener::bind(("127.0.0.1", port)).is_ok();
}
}
#[cfg(windows)]
{
let output = std::process::Command::new("cmd")
.args(["/C", &format!("for /f \"tokens=5\" %a in ('netstat -aon ^| find \":{} \" ^| find \"LISTENING\"') do taskkill /F /PID %a", port)])
.output();
if output.is_ok() {
std::thread::sleep(std::time::Duration::from_millis(500));
return std::net::TcpListener::bind(("127.0.0.1", port)).is_ok();
}
}
false
}
pub fn open_browser(url: &str) {
let _ = if cfg!(target_os = "macos") {
std::process::Command::new("open")
.arg(url)
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
} else if cfg!(target_os = "windows") {
std::process::Command::new("cmd")
.args(["/C", "start", "", url])
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
} else {
std::process::Command::new("xdg-open")
.arg(url)
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
};
}
pub fn resolve_cmd(cmd: &str) -> String {
which::which(cmd)
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_else(|_| cmd.to_string())
}
pub fn php_vendor_bin(name: &str) -> String {
if is_windows() {
format!("vendor\\bin\\{}", name)
} else {
format!("vendor/bin/{}", name)
}
}