diff options
Diffstat (limited to 'helix-view')
-rw-r--r-- | helix-view/src/document.rs | 61 |
1 files changed, 52 insertions, 9 deletions
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 254e01b0..fe9c87f7 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -127,6 +127,36 @@ where } } +/// Expands tilde `~` into users home directory if avilable, otherwise returns the path +/// unchanged. The tilde will only be expanded when present as the first component of the path +/// and only slash follows it. +pub fn expand_tilde(path: &Path) -> PathBuf { + let mut components = path.components().peekable(); + if let Some(Component::Normal(c)) = components.peek() { + if c == &"~" { + if let Ok(home) = helix_core::home_dir() { + // it's ok to unwrap, the path starts with `~` + return home.join(path.strip_prefix("~").unwrap()); + } + } + } + + path.to_path_buf() +} + +/// Replaces users home directory from `path` with tilde `~` if the directory +/// is available, otherwise returns the path unchanged. +pub fn fold_home_dir(path: &Path) -> PathBuf { + if let Ok(home) = helix_core::home_dir() { + if path.starts_with(&home) { + // it's ok to unwrap, the path starts with home dir + return PathBuf::from("~").join(path.strip_prefix(&home).unwrap()); + } + } + + path.to_path_buf() +} + /// Normalize a path, removing things like `.` and `..`. /// /// CAUTION: This does not resolve symlinks (unlike @@ -137,6 +167,7 @@ where /// needs to improve on. /// Copied from cargo: https://github.com/rust-lang/cargo/blob/070e459c2d8b79c5b2ac5218064e7603329c92ae/crates/cargo-util/src/paths.rs#L81 pub fn normalize_path(path: &Path) -> PathBuf { + let path = expand_tilde(path); let mut components = path.components().peekable(); let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { components.next(); @@ -163,12 +194,17 @@ pub fn normalize_path(path: &Path) -> PathBuf { ret } -// Returns the canonical, absolute form of a path with all intermediate components normalized. -// -// This function is used instead of `std::fs::canonicalize` because we don't want to verify -// here if the path exists, just normalize it's components. +/// Returns the canonical, absolute form of a path with all intermediate components normalized. +/// +/// This function is used instead of `std::fs::canonicalize` because we don't want to verify +/// here if the path exists, just normalize it's components. pub fn canonicalize_path(path: &Path) -> std::io::Result<PathBuf> { - std::env::current_dir().map(|current_dir| normalize_path(¤t_dir.join(path))) + let normalized = normalize_path(path); + if normalized.is_absolute() { + Ok(normalized) + } else { + std::env::current_dir().map(|current_dir| current_dir.join(normalized)) + } } use helix_lsp::lsp; @@ -709,12 +745,19 @@ impl Document { &self.selections[&view_id] } - pub fn relative_path(&self) -> Option<&Path> { + pub fn relative_path(&self) -> Option<PathBuf> { let cwdir = std::env::current_dir().expect("couldn't determine current directory"); - self.path - .as_ref() - .map(|path| path.strip_prefix(cwdir).unwrap_or(path)) + self.path.as_ref().map(|path| { + let path = fold_home_dir(path); + if path.is_relative() { + path + } else { + path.strip_prefix(cwdir) + .map(|p| p.to_path_buf()) + .unwrap_or(path) + } + }) } // pub fn slice<R>(&self, range: R) -> RopeSlice where R: RangeBounds { |