use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq)]
pub enum Platform {
MacOS,
Linux,
Windows,
Unknown,
}
#[derive(Debug, Clone)]
pub struct PlatformInfo {
pub platform: Platform,
pub warp_config_dir: Option<PathBuf>,
pub supports_uri_scheme: bool,
}
impl Platform {
pub fn current() -> Self {
if cfg!(target_os = "macos") {
Platform::MacOS
} else if cfg!(target_os = "linux") {
Platform::Linux
} else if cfg!(target_os = "windows") {
Platform::Windows
} else {
Platform::Unknown
}
}
pub fn display_name(&self) -> &'static str {
match self {
Platform::MacOS => "macOS",
Platform::Linux => "Linux",
Platform::Windows => "Windows",
Platform::Unknown => "Unknown",
}
}
pub fn supports_warp(&self) -> bool {
match self {
Platform::MacOS => true,
Platform::Linux => true,
Platform::Windows => true, Platform::Unknown => false,
}
}
}
impl PlatformInfo {
pub fn current() -> Self {
let platform = Platform::current();
let warp_config_dir = get_warp_config_dir(&platform);
let supports_uri_scheme = platform.supports_warp();
PlatformInfo {
platform,
warp_config_dir,
supports_uri_scheme,
}
}
pub fn get_warp_shortcuts(&self) -> WarpShortcuts {
match self.platform {
Platform::MacOS => WarpShortcuts {
command_palette: "CMD-P",
launch_config_palette: "CMD-L",
active_window_modifier: "CMD-ENTER",
ctrl_modifier: "CMD",
},
Platform::Linux | Platform::Windows => WarpShortcuts {
command_palette: "CTRL-SHIFT-P",
launch_config_palette: "CTRL-L",
active_window_modifier: "CTRL-ENTER",
ctrl_modifier: "CTRL",
},
Platform::Unknown => WarpShortcuts {
command_palette: "CMD-P / CTRL-SHIFT-P",
launch_config_palette: "CMD-L / CTRL-L",
active_window_modifier: "CMD-ENTER / CTRL-ENTER",
ctrl_modifier: "CMD / CTRL",
},
}
}
}
#[derive(Debug, Clone)]
pub struct WarpShortcuts {
pub command_palette: &'static str,
pub launch_config_palette: &'static str,
pub active_window_modifier: &'static str,
pub ctrl_modifier: &'static str,
}
fn get_warp_config_dir(platform: &Platform) -> Option<PathBuf> {
match platform {
Platform::MacOS => {
dirs::home_dir().map(|home| home.join(".warp").join("launch_configurations"))
}
Platform::Linux => {
dirs::config_dir()
.map(|config| config.join("warp-terminal").join("launch_configurations"))
.or_else(|| {
dirs::home_dir().map(|home| home.join(".warp").join("launch_configurations"))
})
}
Platform::Windows => {
dirs::config_dir()
.map(|config| config.join("warp-terminal").join("launch_configurations"))
}
Platform::Unknown => None,
}
}
pub fn is_binary_available(binary_name: &str) -> bool {
std::process::Command::new(binary_name)
.arg("--version")
.output()
.map(|output| output.status.success())
.unwrap_or(false)
}
pub fn check_automation_availability() -> AutomationAvailability {
let platform = Platform::current();
match platform {
Platform::MacOS => {
let osascript = std::process::Command::new("which")
.arg("osascript")
.output()
.map(|output| output.status.success())
.unwrap_or(false);
AutomationAvailability {
platform,
tool_name: "osascript",
is_available: osascript,
install_hint: if !osascript {
Some("osascript should be available by default on macOS")
} else {
None
},
}
}
Platform::Linux => {
let xdotool = std::process::Command::new("which")
.arg("xdotool")
.output()
.map(|output| output.status.success())
.unwrap_or(false);
AutomationAvailability {
platform,
tool_name: "xdotool",
is_available: xdotool,
install_hint: if !xdotool {
Some("Install xdotool: sudo apt-get install xdotool (Debian/Ubuntu) or equivalent")
} else {
None
},
}
}
Platform::Windows => {
let powershell = std::process::Command::new("powershell")
.args(["-Command", "echo test"])
.output()
.map(|output| output.status.success())
.unwrap_or(false);
AutomationAvailability {
platform,
tool_name: "PowerShell",
is_available: powershell,
install_hint: if !powershell {
Some("PowerShell should be available by default on Windows")
} else {
None
},
}
}
Platform::Unknown => AutomationAvailability {
platform,
tool_name: "none",
is_available: false,
install_hint: Some("Platform not supported for automation"),
},
}
}
#[derive(Debug, Clone)]
pub struct AutomationAvailability {
pub platform: Platform,
pub tool_name: &'static str,
pub is_available: bool,
pub install_hint: Option<&'static str>,
}
pub fn open_uri(uri: &str) -> Result<(), std::io::Error> {
match Platform::current() {
Platform::MacOS => {
std::process::Command::new("open").arg(uri).spawn()?;
}
Platform::Linux => {
std::process::Command::new("xdg-open").arg(uri).spawn()?;
}
Platform::Windows => {
std::process::Command::new("cmd")
.args(["/c", "start", uri])
.spawn()?;
}
Platform::Unknown => {
return Err(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"Unsupported platform for URI opening",
));
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_platform_detection() {
let platform = Platform::current();
assert_ne!(platform, Platform::Unknown);
let info = PlatformInfo::current();
assert_eq!(info.platform, platform);
}
#[test]
fn test_platform_display_names() {
assert_eq!(Platform::MacOS.display_name(), "macOS");
assert_eq!(Platform::Linux.display_name(), "Linux");
assert_eq!(Platform::Windows.display_name(), "Windows");
assert_eq!(Platform::Unknown.display_name(), "Unknown");
}
#[test]
fn test_warp_support() {
assert!(Platform::MacOS.supports_warp());
assert!(Platform::Linux.supports_warp());
assert!(Platform::Windows.supports_warp());
assert!(!Platform::Unknown.supports_warp());
}
#[test]
fn test_warp_shortcuts() {
let macos_info = PlatformInfo {
platform: Platform::MacOS,
warp_config_dir: None,
supports_uri_scheme: true,
};
let shortcuts = macos_info.get_warp_shortcuts();
assert_eq!(shortcuts.command_palette, "CMD-P");
assert_eq!(shortcuts.ctrl_modifier, "CMD");
let linux_info = PlatformInfo {
platform: Platform::Linux,
warp_config_dir: None,
supports_uri_scheme: true,
};
let shortcuts = linux_info.get_warp_shortcuts();
assert_eq!(shortcuts.command_palette, "CTRL-SHIFT-P");
assert_eq!(shortcuts.ctrl_modifier, "CTRL");
}
}