//! Pure project-selection logic — no I/O, no async, no side effects. //! //! All functions here are deterministic and depend only on their arguments. /// Promote a project path to the front of the known-projects list. /// /// Removes any existing occurrence of `path` and inserts it at position 0, /// so the most-recently-opened project is always first. pub fn promote_to_front(mut projects: Vec, path: &str) -> Vec { projects.retain(|p| p != path); projects.insert(0, path.to_string()); projects } #[allow(dead_code)] /// Extract the display name for a project from its filesystem path. /// /// Returns the last non-empty path component, or `None` for root or empty input. pub fn project_name_from_path(path: &str) -> Option<&str> { path.trim_end_matches('/') .rsplit('/') .find(|s| !s.is_empty()) } #[cfg(test)] mod tests { use super::*; #[test] fn promote_to_front_inserts_new_path_at_position_zero() { let result = promote_to_front(vec!["/a".to_string(), "/b".to_string()], "/c"); assert_eq!(result, vec!["/c", "/a", "/b"]); } #[test] fn promote_to_front_moves_existing_entry_to_front() { let result = promote_to_front( vec!["/a".to_string(), "/b".to_string(), "/c".to_string()], "/b", ); assert_eq!(result, vec!["/b", "/a", "/c"]); } #[test] fn promote_to_front_is_idempotent_when_already_first() { let result = promote_to_front(vec!["/a".to_string(), "/b".to_string()], "/a"); assert_eq!(result, vec!["/a", "/b"]); } #[test] fn promote_to_front_handles_empty_list() { let result = promote_to_front(vec![], "/new"); assert_eq!(result, vec!["/new"]); } #[test] fn promote_to_front_deduplicates_single_entry() { let result = promote_to_front(vec!["/a".to_string()], "/a"); assert_eq!(result, vec!["/a"]); } #[test] fn project_name_from_path_extracts_last_component() { assert_eq!( project_name_from_path("/home/user/myproject"), Some("myproject") ); } #[test] fn project_name_from_path_handles_trailing_slash() { assert_eq!( project_name_from_path("/home/user/myproject/"), Some("myproject") ); } #[test] fn project_name_from_path_returns_none_for_root() { assert_eq!(project_name_from_path("/"), None); } #[test] fn project_name_from_path_returns_none_for_empty() { assert_eq!(project_name_from_path(""), None); } #[test] fn project_name_from_path_handles_single_component() { assert_eq!(project_name_from_path("myproject"), Some("myproject")); } #[test] fn project_name_from_path_handles_deep_path() { assert_eq!( project_name_from_path("/a/b/c/d/project-name"), Some("project-name") ); } }