Skip to main content

lean_ctx/core/
portable_binary.rs

1pub fn resolve_portable_binary() -> String {
2    let which_cmd = if cfg!(windows) { "where" } else { "which" };
3    if let Ok(output) = std::process::Command::new(which_cmd)
4        .arg("lean-ctx")
5        .stderr(std::process::Stdio::null())
6        .output()
7    {
8        if output.status.success() {
9            let raw = String::from_utf8_lossy(&output.stdout).trim().to_string();
10            if !raw.is_empty() {
11                let path = pick_best_binary_line(&raw);
12                return sanitize_exe_path(path);
13            }
14        }
15    }
16    let path = std::env::current_exe()
17        .map(|p| p.to_string_lossy().to_string())
18        .unwrap_or_else(|_| "lean-ctx".to_string());
19    sanitize_exe_path(path)
20}
21
22/// On Windows, `where lean-ctx` returns multiple lines (e.g. `lean-ctx` and
23/// `lean-ctx.cmd`). Pick the `.cmd`/`.exe` variant if available, otherwise
24/// the first line.
25fn pick_best_binary_line(raw: &str) -> String {
26    let lines: Vec<&str> = raw
27        .lines()
28        .map(|l| l.trim())
29        .filter(|l| !l.is_empty())
30        .collect();
31    if lines.len() <= 1 {
32        return lines.first().unwrap_or(&"lean-ctx").to_string();
33    }
34    if cfg!(windows) {
35        if let Some(cmd) = lines
36            .iter()
37            .find(|l| l.ends_with(".cmd") || l.ends_with(".exe"))
38        {
39            return cmd.to_string();
40        }
41    }
42    lines[0].to_string()
43}
44
45fn sanitize_exe_path(path: String) -> String {
46    path.trim_end_matches(" (deleted)").to_string()
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn single_line_returns_as_is() {
55        assert_eq!(
56            pick_best_binary_line("/usr/bin/lean-ctx"),
57            "/usr/bin/lean-ctx"
58        );
59    }
60
61    #[test]
62    fn multiline_returns_first_line() {
63        let raw = "/usr/bin/lean-ctx\n/usr/local/bin/lean-ctx";
64        let result = pick_best_binary_line(raw);
65        assert_eq!(result, "/usr/bin/lean-ctx");
66    }
67
68    #[test]
69    fn empty_returns_fallback() {
70        assert_eq!(pick_best_binary_line(""), "lean-ctx");
71    }
72
73    #[test]
74    fn sanitize_removes_deleted_suffix() {
75        assert_eq!(
76            sanitize_exe_path("/usr/bin/lean-ctx (deleted)".to_string()),
77            "/usr/bin/lean-ctx"
78        );
79    }
80
81    #[test]
82    fn whitespace_lines_are_filtered() {
83        let raw = "  /usr/bin/lean-ctx  \n  \n  /usr/local/bin/lean-ctx  ";
84        assert_eq!(pick_best_binary_line(raw), "/usr/bin/lean-ctx");
85    }
86}