diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 5440f9caa2..7884d7fab9 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -858,6 +858,8 @@ fn do_auto_cd( report_shell_error(engine_state, &err); return; }; + use nu_path::pwd_per_drive::pwd_per_drive::set_pwd_per_drive; + let _as_is = set_pwd_per_drive(PathBuf::from(path.clone()).as_path()); let cwd = Value::string(cwd, span); let shells = stack.get_env_var(engine_state, "NUSHELL_SHELLS"); diff --git a/crates/nu-command/src/filesystem/cd.rs b/crates/nu-command/src/filesystem/cd.rs index 67ee4a6e9d..81e93e6ec0 100644 --- a/crates/nu-command/src/filesystem/cd.rs +++ b/crates/nu-command/src/filesystem/cd.rs @@ -114,19 +114,9 @@ impl Command for Cd { //FIXME: this only changes the current scope, but instead this environment variable //should probably be a block that loads the information from the state in the overlay PermissionResult::PermissionOk => { - let path_for_scd = path.clone(); + use nu_path::pwd_per_drive::pwd_per_drive::set_pwd_per_drive; + let _as_is = set_pwd_per_drive(path.as_path()); stack.set_cwd(path)?; - use nu_path::state_driver_pwd::get_drive_pwd_map; - get_drive_pwd_map().lock().unwrap().set_pwd(path_for_scd.as_path()) - .map_err(|_e| { - Err(ShellError::GenericError{ - error: "Set PWD for drive failed".into(), - msg: "System error".into(), - span: None, - help: None, - inner: vec![], - }) - })?; Ok(PipelineData::empty()) } PermissionResult::PermissionDenied(reason) => Err(ShellError::IOError { diff --git a/crates/nu-path/Cargo.toml b/crates/nu-path/Cargo.toml index 59de73e5e4..762859f8cb 100644 --- a/crates/nu-path/Cargo.toml +++ b/crates/nu-path/Cargo.toml @@ -13,12 +13,12 @@ bench = false [dependencies] dirs = { workspace = true } +cfg-if = "1.0.0" [target.'cfg(windows)'.dependencies] omnipath = { workspace = true } once_cell = "1.20.1" winapi = { version = "0.3.9", features = ["fileapi"] } -windows-sys = { workspace = true, features = ["Win32_System_Environment"] } [target.'cfg(all(unix, not(target_os = "macos"), not(target_os = "android")))'.dependencies] pwd = { workspace = true } diff --git a/crates/nu-path/src/lib.rs b/crates/nu-path/src/lib.rs index 2d4ecb7d88..145013e7fe 100644 --- a/crates/nu-path/src/lib.rs +++ b/crates/nu-path/src/lib.rs @@ -4,11 +4,12 @@ mod components; pub mod dots; pub mod expansions; pub mod form; +#[cfg(target_os="windows")] +pub mod pwd_per_drive; mod helpers; mod path; mod tilde; mod trailing_slash; -pub mod state_driver_pwd; pub use components::components; pub use expansions::{canonicalize_with, expand_path_with, expand_to_real_path, locate_in_dirs}; diff --git a/crates/nu-path/src/pwd_per_drive.rs b/crates/nu-path/src/pwd_per_drive.rs new file mode 100644 index 0000000000..a9f8238319 --- /dev/null +++ b/crates/nu-path/src/pwd_per_drive.rs @@ -0,0 +1,348 @@ +cfg_if::cfg_if! { + if #[cfg(target_os="windows")] { + +use once_cell::sync::Lazy; +use std::path::{ Path, PathBuf }; +use std::sync::Mutex; + +struct DrivePWDmap { + map: [Option; 26], // Fixed-size array for A-Z +} + +impl DrivePWDmap { + pub fn new() -> Self { + DrivePWDmap { + map: Default::default(), // Initialize all to `None` + } + } + + /// Set the PWD for the drive letter in the path which is an absolute path + pub fn set_pwd(&mut self, path: &Path) -> Result<(), String> { + if let Some(drive_letter) = Self::extract_drive_letter(path) { + if let Some(index) = Self::drive_to_index(drive_letter) { + if let Some(path_str) = path.to_str() { + self.map[index] = Some(path_str.to_string()); + Ok(()) + } else { + Err(format!("Invalid path: {}", path.display())) + } + } else { + Err(format!("Invalid drive letter: {}", drive_letter)) + } + } else { + Err(format!("Invalid path: {}", path.display())) + } + } + + /// Get the PWD for a drive letter, if not yet, try using + /// winapi GetFullPathNameW to get "T:", "T:/" can be default + pub fn get_pwd(&mut self, drive: char) -> Option { + Self::drive_to_index(drive).map(|index| { + self.map[index] + .clone() + .unwrap_or_else(|| + if let Some(system_pwd) = get_full_path_name_w(&format!("{}:", drive.to_ascii_uppercase())) { + self.map[index] = Some(system_pwd.clone()); + system_pwd + } else { + format!("{}:/", drive.to_ascii_uppercase()) + } + ) + }) + } + + /// Expand a relative path using the PWD of the drive + pub fn expand_path(&mut self, path: &Path) -> Option { + let path_str = path.to_str()?; + if let Some(drive_letter) = Self::extract_drive_letter(path) { + if let Some(pwd) = self.get_pwd(drive_letter) { + // Combine current PWD with the relative path + let mut base = PathBuf::from(Self::ensure_trailing_separator(&pwd)); + base.push(path_str.split_at(2).1); // Skip the "C:" part of the relative path + Some(base) + } else { + None // PWD on Drive letter not found + } + } else { + None // Invalid or no drive letter + } + } + + /// Helper to convert a drive letter to an array index + fn drive_to_index(drive: char) -> Option { + let drive = drive.to_ascii_uppercase(); + if ('A'..='Z').contains(&drive) { + Some((drive as usize) - ('A' as usize)) + } else { + None + } + } + + /// Extract the drive letter from a path (e.g., `C:test` -> `C`) + fn extract_drive_letter(path: &Path) -> Option { + path.to_str() + .and_then(|s| s.chars().next()) + .filter(|c| c.is_ascii_alphabetic()) + } + + /// Ensure a path has a trailing `\` + fn ensure_trailing_separator(path: &str) -> String { + if !path.ends_with('\\') && !path.ends_with('/') { + format!("{}/", path) + } else { + path.to_string() + } + } +} + +// GetFullPathW +fn get_full_path_name_w(path_str: &str) -> Option { + use std::ffi::OsString; + use std::os::windows::ffi::OsStringExt; + use std::os::windows::ffi::OsStrExt; + use winapi::um::fileapi::GetFullPathNameW; + use winapi::um::winnt::WCHAR; + + const MAX_PATH : usize = 260; + let mut buffer: [WCHAR; MAX_PATH] = [0; MAX_PATH]; + + unsafe { + // Convert input to wide string. + let wide_path: Vec = OsString::from(path_str).encode_wide().chain(Some(0)).collect(); + let length = GetFullPathNameW( + wide_path.as_ptr(), + buffer.len() as u32, + buffer.as_mut_ptr(), + std::ptr::null_mut(), + ); + + if length > 0 && (length as usize) < MAX_PATH { + let path = OsString::from_wide(&buffer[..length as usize]); + if let Some(path_str) = path.to_str() { + let path_string = path_str.to_string(); + { + return Some(path_string); + } + } + } + } + None +} + +/// Global singleton instance of DrivePwdMap +static DRIVE_PWD_MAP: Lazy> = Lazy::new(|| Mutex::new(DrivePWDmap::new())); + +/// Public API to access the singleton instance +fn get_drive_pwd_map() -> &'static Mutex { + &DRIVE_PWD_MAP +} + +/// Test for DrivePWD map +#[cfg(test)] +mod tests { + use super::*; + use std::path::Path; + + #[test] + fn test_singleton_set_and_get_pwd() { + let drive_pwd_map = get_drive_pwd_map(); + { + let mut map = drive_pwd_map.lock().unwrap(); + + // Set PWD for drive C + assert!(map.set_pwd(Path::new("C:\\Users\\Example")).is_ok()); + } + + { + let map = drive_pwd_map.lock().unwrap(); + + // Get PWD for drive C + assert_eq!(map.get_pwd('C'), Some("C:\\Users\\Example".to_string())); + + // Get PWD for drive E (not set, should return E:\) + assert_eq!(map.get_pwd('E'), Some("E:\\".to_string())); + } + } + #[test] + fn test_expand_path() { + let mut drive_map = DrivePWDmap::new(); + + // Set PWD for drive C + drive_map.set_pwd(Path::new("C:\\Users\\Home")).unwrap(); + + // Expand a relative path + let expanded = drive_map.expand_path(Path::new("C:test")); + assert_eq!(expanded, Some(PathBuf::from("C:\\Users\\Home\\test"))); + + // Expand an absolute path + let expanded = drive_map.expand_path(Path::new("C:\\absolute\\path")); + assert_eq!(expanded, Some(PathBuf::from("C:\\absolute\\path"))); + + // Expand with no drive letter + let expanded = drive_map.expand_path(Path::new("\\no_drive")); + assert_eq!(expanded, None); + + // Expand with no PWD set for the drive + let expanded = drive_map.expand_path(Path::new("D:test")); + assert_eq!(expanded, Some(PathBuf::from("D:\\test"))); + } + + #[test] + fn test_set_and_get_pwd() { + let mut drive_map = DrivePWDmap::new(); + + // Set PWD for drive C + assert!(drive_map.set_pwd(Path::new("C:\\Users\\Example")).is_ok()); + assert_eq!(drive_map.get_pwd('C'), Some("C:\\Users\\Example".to_string())); + + // Set PWD for drive D + assert!(drive_map.set_pwd(Path::new("D:\\Projects")).is_ok()); + assert_eq!(drive_map.get_pwd('D'), Some("D:\\Projects".to_string())); + + // Get PWD for drive E (not set, should return E:\) + assert_eq!(drive_map.get_pwd('E'), Some("E:\\".to_string())); + } + + #[test] + fn test_set_pwd_invalid_path() { + let mut drive_map = DrivePWDmap::new(); + + // Invalid path (no drive letter) + let result = drive_map.set_pwd(Path::new("\\InvalidPath")); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "Invalid path: \\InvalidPath"); + } + + #[test] + fn test_get_pwd_invalid_drive() { + let drive_map = DrivePWDmap::new(); + + // Get PWD for a drive not set (e.g., Z) + assert_eq!(drive_map.get_pwd('Z'), Some("Z:\\".to_string())); + + // Invalid drive letter (non-alphabetic) + assert_eq!(drive_map.get_pwd('1'), None); + } + + #[test] + fn test_drive_to_index() { + // Valid drive letters + assert_eq!(DrivePWDmap::drive_to_index('A'), Some(0)); + assert_eq!(DrivePWDmap::drive_to_index('Z'), Some(25)); + // Valid drive letters + assert_eq!(DrivePWDmap::drive_to_index('a'), Some(0)); + assert_eq!(DrivePWDmap::drive_to_index('z'), Some(25)); + for i in 1..25 { + assert_eq!(DrivePWDmap::drive_to_index(std::char::from_u32(('A' as usize + i) as u32).unwrap()), Some(i)); + assert_eq!(DrivePWDmap::drive_to_index(std::char::from_u32(('a' as usize + i) as u32).unwrap()), Some(i)); + } + + // Invalid drive letters + assert_eq!(DrivePWDmap::drive_to_index('1'), None); + assert_eq!(DrivePWDmap::drive_to_index('$'), None); + } +}}} + +/// Usage for pwd_per_drive +/// +/// Upon change PWD, call set_pwd_per_drive() with absolute path +/// +/// Call expand_pwd_per_drive() with relative path to get absolution path +/// +/// Doctest +/// ```Rust +/// // Set PWD for drive C +/// set_pwd_per_drive(Path::new("C:\\Users\\Home")).unwrap(); +/// +/// // Expand a relative path +/// let expanded = expand_pwd_per_drive(Path::new("C:test")); +/// assert_eq!(expanded, Some(PathBuf::from("C:\\Users\\Home\\test"))); +/// +/// // Will NOT expand an absolute path +/// let expanded = expand_pwd_per_drive(Path::new("C:\\absolute\\path")); +/// assert_eq!(expanded, None); +/// +/// // Expand with no drive letter +/// let expanded = expand_pwd_per_drive(Path::new("\\no_drive")); +/// assert_eq!(expanded, None); +/// +/// // Expand with no PWD set for the drive +/// let expanded = expand_pwd_per_drive(Path::new("D:test")); +/// assert_eq!(expanded, Some(PathBuf::from("D:\\test"))); +/// ``` +pub mod pwd_per_drive { + use std::path::{ Path, PathBuf }; + use super::{get_drive_pwd_map}; + + /// set_pwd_per_drive + /// record PWD for drive, path must be absolute path + /// return Ok(()) if succeeded, otherwise error message + #[cfg(target_os = "windows")] + pub fn set_pwd_per_drive(path: &Path) -> Result<(), String> { + get_drive_pwd_map().lock().unwrap().set_pwd(path) + } + + #[cfg(not(target_os = "windows"))] + pub fn set_pwd_per_drive(path: &Path) -> Result<(), String> { + Ok(()) + } + + /// expand_pwe_per_drive + /// input relative path, expand PWD to construct absolute path + /// return PathBuf for absolute path, None if input path is invalid + #[cfg(target_os = "windows")] + pub fn expand_pwd_per_drive(path: &Path) -> Option { + if need_expand_pwd_per_drive(path) { + get_drive_pwd_map().lock().unwrap().expand_path(path) + } else { + None + } + } + + /// expand_pwd_per_drive will return None on non-windows platform + #[cfg(not(target_os = "windows"))] + pub fn expand_pwd_per_drive(_path: &Path) -> Option { + None + } + + /// If input path is relative path with drive letter, + /// it can be expanded with PWD per drive + #[cfg(target_os = "windows")] + fn need_expand_pwd_per_drive(path: &Path) -> bool { + if let Some(path_str) = path.to_str() { + let chars: Vec = path_str.chars().collect(); + if chars.len() >= 2 { + return chars[1] == ':' && (chars.len() == 2 || (chars[2] != '/' && chars[2] != '\\')); + } + } + false + } + + /// On non-windows platform, will not expand + #[cfg(not(target_os = "windows"))] + fn need_expand_pwd_per_drive(path: &Path) -> bool { + false + } + + #[test] + fn test_usage_for_pwd_per_drive() { + // Set PWD for drive C + set_pwd_per_drive(Path::new("C:\\Users\\Home")).unwrap(); + + // Expand a relative path + let expanded = expand_pwd_per_drive(Path::new("C:test")); + assert_eq!(expanded, Some(PathBuf::from("C:\\Users\\Home\\test"))); + + // Will NOT expand an absolute path + let expanded = expand_pwd_per_drive(Path::new("C:\\absolute\\path")); + assert_eq!(expanded, None); + + // Expand with no drive letter + let expanded = expand_pwd_per_drive(Path::new("\\no_drive")); + assert_eq!(expanded, None); + + // Expand with no PWD set for the drive + let expanded = expand_pwd_per_drive(Path::new("D:test")); + assert_eq!(expanded, Some(PathBuf::from("D:\\test"))); + } +} \ No newline at end of file diff --git a/crates/nu-path/src/state_driver_pwd.rs b/crates/nu-path/src/state_driver_pwd.rs deleted file mode 100644 index 267438954a..0000000000 --- a/crates/nu-path/src/state_driver_pwd.rs +++ /dev/null @@ -1,301 +0,0 @@ -use std::path::{ Path, PathBuf }; - -pub struct DrivePwdMap { - map: [Option; 26], // Fixed-size array for A-Z -} - -impl DrivePwdMap { - pub fn new() -> Self { - DrivePwdMap { - map: Default::default(), // Initialize all to `None` - } - } - - /// Set the current working directory based on the drive letter in the path - pub fn set_pwd(&mut self, path: &Path) -> Result<(), String> { - if let Some(drive_letter) = Self::extract_drive_letter(path) { - if let Some(index) = Self::drive_to_index(drive_letter) { - let normalized = Self::normalize_path(path); - self.map[index] = Some(normalized.to_string_lossy().into_owned()); - Ok(()) - } else { - Err(format!("Invalid drive letter: {}", drive_letter)) - } - } else { - Err(format!("Invalid path: {}", path.display())) - } - } - - /// Get the current working directory for a drive letter - pub fn get_pwd(&self, drive: char) -> Option { - Self::drive_to_index(drive).map(|index| { - self.map[index] - .clone() - .unwrap_or_else(|| format!("{}:\\", drive.to_ascii_uppercase())) - }) - } - - /// Expand a relative path using the current working directory of the drive - pub fn expand_path(&self, path: &Path) -> Option { - let path_str = path.to_str()?; - if let Some(drive_letter) = Self::extract_drive_letter(path) { - let is_absolute = path_str.contains(":\\") || path_str.starts_with("\\"); - if is_absolute { - // Already an absolute path - Some(PathBuf::from(Self::ensure_trailing_separator(path_str))) - } else if let Some(pwd) = self.get_pwd(drive_letter) { - // Combine current PWD with the relative path - let mut base = PathBuf::from(Self::ensure_trailing_separator(&pwd)); - base.push(path_str.split_at(2).1); // Skip the "C:" part of the relative path - Some(base) - } else { - None // Drive letter not found - } - } else { - None // Invalid or no drive letter - } - } - - /// Helper to convert a drive letter to an array index - fn drive_to_index(drive: char) -> Option { - let drive = drive.to_ascii_uppercase(); - if ('A'..='Z').contains(&drive) { - Some((drive as usize) - ('A' as usize)) - } else { - None - } - } - - /// Extract the drive letter from a path (e.g., `C:test` -> `C`) - fn extract_drive_letter(path: &Path) -> Option { - path.to_str() - .and_then(|s| s.chars().next()) - .filter(|c| c.is_ascii_alphabetic()) - } - - /// Normalize a path by removing any trailing `\` or `/` - fn normalize_path(path: &Path) -> PathBuf { - let mut normalized = path.to_path_buf(); - while normalized.to_string_lossy().ends_with(&['\\', '/'][..]) { - normalized.pop(); - } - normalized - } - - /// Ensure a path has a trailing `\` - fn ensure_trailing_separator(path: &str) -> String { - if !path.ends_with('\\') && !path.ends_with('/') { - format!("{}\\", path) - } else { - path.to_string() - } - } -} - -use once_cell::sync::Lazy; -use std::sync::Mutex; -//use nu_protocol::errors::shell_error::ShellError; - -/// Global singleton instance of DrivePwdMap -static DRIVE_PWD_MAP: Lazy> = Lazy::new(|| Mutex::new(DrivePwdMap::new())); - -/// Public API to access the singleton instance -pub fn get_drive_pwd_map() -> &'static Mutex { - &DRIVE_PWD_MAP -} - -#[cfg(test)] -mod tests { - use super::*; - use std::path::Path; - - #[test] - fn test_expand_path() { - let mut drive_map = DrivePwdMap::new(); - - // Set PWD for drive C - drive_map.set_pwd(Path::new("C:\\Users\\Home")).unwrap(); - - // Expand a relative path - let expanded = drive_map.expand_path(Path::new("C:test")); - assert_eq!(expanded, Some(PathBuf::from("C:\\Users\\Home\\test"))); - - // Expand an absolute path - let expanded = drive_map.expand_path(Path::new("C:\\absolute\\path")); - assert_eq!(expanded, Some(PathBuf::from("C:\\absolute\\path"))); - - // Expand with no drive letter - let expanded = drive_map.expand_path(Path::new("\\no_drive")); - assert_eq!(expanded, None); - - // Expand with no PWD set for the drive - let expanded = drive_map.expand_path(Path::new("D:test")); - assert_eq!(expanded, Some(PathBuf::from("D:\\test"))); - } - #[test] - fn test_singleton_set_and_get_pwd() { - let drive_pwd_map = get_drive_pwd_map(); - { - let mut map = drive_pwd_map.lock().unwrap(); - - // Set PWD for drive C - assert!(map.set_pwd(Path::new("C:\\Users\\Example")).is_ok()); - } - - { - let map = drive_pwd_map.lock().unwrap(); - - // Get PWD for drive C - assert_eq!(map.get_pwd('C'), Some("C:\\Users\\Example".to_string())); - - // Get PWD for drive E (not set, should return E:\) - assert_eq!(map.get_pwd('E'), Some("E:\\".to_string())); - } - } - - #[test] - fn test_set_and_get_pwd() { - let mut drive_map = DrivePwdMap::new(); - - // Set PWD for drive C - assert!(drive_map.set_pwd(Path::new("C:\\Users\\Example")).is_ok()); - assert_eq!(drive_map.get_pwd('C'), Some("C:\\Users\\Example".to_string())); - - // Set PWD for drive D - assert!(drive_map.set_pwd(Path::new("D:\\Projects")).is_ok()); - assert_eq!(drive_map.get_pwd('D'), Some("D:\\Projects".to_string())); - - // Get PWD for drive E (not set, should return E:\) - assert_eq!(drive_map.get_pwd('E'), Some("E:\\".to_string())); - } - - #[test] - fn test_set_pwd_invalid_path() { - let mut drive_map = DrivePwdMap::new(); - - // Invalid path (no drive letter) - let result = drive_map.set_pwd(Path::new("\\InvalidPath")); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), "Invalid path: \\InvalidPath"); - } - - #[test] - fn test_get_pwd_invalid_drive() { - let drive_map = DrivePwdMap::new(); - - // Get PWD for a drive not set (e.g., Z) - assert_eq!(drive_map.get_pwd('Z'), Some("Z:\\".to_string())); - - // Invalid drive letter (non-alphabetic) - assert_eq!(drive_map.get_pwd('1'), None); - } - - #[test] - fn test_drive_to_index() { - // Valid drive letters - assert_eq!(DrivePwdMap::drive_to_index('A'), Some(0)); - assert_eq!(DrivePwdMap::drive_to_index('Z'), Some(25)); - // Valid drive letters - assert_eq!(DrivePwdMap::drive_to_index('a'), Some(0)); - assert_eq!(DrivePwdMap::drive_to_index('z'), Some(25)); - for i in 1..25 { - assert_eq!(DrivePwdMap::drive_to_index(std::char::from_u32(('A' as usize + i) as u32).unwrap()), Some(i)); - assert_eq!(DrivePwdMap::drive_to_index(std::char::from_u32(('a' as usize + i) as u32).unwrap()), Some(i)); - } - - // Invalid drive letters - assert_eq!(DrivePwdMap::drive_to_index('1'), None); - assert_eq!(DrivePwdMap::drive_to_index('$'), None); - } -} - -pub mod current_directory_specific { - use std::path::Path; - - #[cfg(target_os = "windows")] - pub fn need_expand_current_directory_per_drive(path: &Path) -> bool { - if let Some(path_str) = path.to_str() { - let chars: Vec = path_str.chars().collect(); - if chars.len() >= 2 { - return chars[1] == ':' && (chars.len() == 2 || (chars[2] != '/' && chars[2] != '\\')); - } - } - false - } - - #[cfg(not(target_os = "windows"))] - pub fn need_expand_current_directory(path: &Path) -> bool { - false - } - - #[cfg(target_os = "windows")] - pub fn get_windows_absolute_path(path: &Path) -> Option { - use std::ffi::OsString; - use std::os::windows::ffi::OsStringExt; - use std::os::windows::ffi::OsStrExt; - use winapi::um::fileapi::GetFullPathNameW; - use winapi::um::winnt::WCHAR; - - const MAX_PATH : usize = 260; - let mut buffer: [WCHAR; MAX_PATH] = [0; MAX_PATH]; - - if let Some(path_str) = path.to_str() { - unsafe { - // Convert input to wide string. - let wide_path: Vec = OsString::from(path_str).encode_wide().chain(Some(0)).collect(); - let length = GetFullPathNameW( - wide_path.as_ptr(), - buffer.len() as u32, - buffer.as_mut_ptr(), - std::ptr::null_mut(), - ); - - if length > 0 { - let abs_path = OsString::from_wide(&buffer[..length as usize]); - if let Some(abs_path_str) = abs_path.to_str() { - let abs_path_string = abs_path_str.to_string(); - return Some(abs_path_string); - } - } - } - } - - None - } - - pub enum DrivePwdError { - InvalidPath, - SystemError, - } - #[cfg(not(target_os = "windows"))] - fn get_windows_absolute_path(path: &Path) -> Option { - None - } - #[cfg(target_os = "windows")] - pub fn set_current_directory_windows(path: &Path) -> Result<(), DrivePwdError> { - use std::ffi::OsString; - use std::os::windows::ffi::OsStrExt; - use windows_sys::Win32::System::Environment::SetCurrentDirectoryW; - - if let Some(path_str) = path.to_str() { - unsafe { - // Convert input to wide string. - let wide_path: Vec = OsString::from(path_str).encode_wide().chain(Some(0)).collect(); - if SetCurrentDirectoryW(wide_path.as_ptr()) != 0 { - println!("Successfully changed the current directory to {}", path_str); - return Ok(()) - } else { - return - Err(DrivePwdError::SystemError) - - }; - } - } - Err(DrivePwdError::InvalidPath) - } - - #[cfg(not(target_os = "windows"))] - pub fn set_current_directory_windows(_path: &Path) -> Result<(), Error>{ - Ok(()) - } -} \ No newline at end of file diff --git a/crates/nu-path/src/tilde.rs b/crates/nu-path/src/tilde.rs index 360810b86c..fe44fa07aa 100644 --- a/crates/nu-path/src/tilde.rs +++ b/crates/nu-path/src/tilde.rs @@ -21,21 +21,11 @@ fn expand_tilde_with_home(path: impl AsRef, home: Option) -> Path let path = path.as_ref(); if !path.starts_with("~") { - use crate::state_driver_pwd:: { - current_directory_specific::need_expand_current_directory_per_drive, - //current_directory_specific::get_windows_absolute_path, - get_drive_pwd_map + use crate::pwd_per_drive:: { + pwd_per_drive::expand_pwd_per_drive, }; - if need_expand_current_directory_per_drive(path) { - if let Some(expanded_dir) = get_drive_pwd_map().lock().unwrap().expand_path(path) { - return PathBuf::from(&expanded_dir) - } - // if let Some(current_dir) = get_windows_absolute_path(path) { - // //println!("Absolute path for {} is: {}", path.display(), current_dir); - // return PathBuf::from(¤t_dir) - // } else { - // println!("Failed to get absolute path for {}", path.display()); - // } + if let Some(expanded_dir) = expand_pwd_per_drive(path) { + return expanded_dir; } let string = path.to_string_lossy(); let mut path_as_string = string.as_ref().bytes();