From ce25aa951e4bd4352fc211258014557e69cc5c5c Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Tue, 1 Jun 2021 14:47:21 +0900 Subject: Allow setting a filepath on :write --- helix-view/src/document.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'helix-view/src/document.rs') diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 7d912ec0..51d8a795 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -1,6 +1,6 @@ use anyhow::{Context, Error}; use std::future::Future; -use std::path::{Path, PathBuf}; +use std::path::{Component, Path, PathBuf}; use std::sync::Arc; use helix_core::{ @@ -64,6 +64,42 @@ where } } +/// Normalize a path, removing things like `.` and `..`. +/// +/// CAUTION: This does not resolve symlinks (unlike +/// [`std::fs::canonicalize`]). This may cause incorrect or surprising +/// behavior at times. This should be used carefully. Unfortunately, +/// [`std::fs::canonicalize`] can be hard to use correctly, since it can often +/// fail, or on Windows returns annoying device paths. This is a problem Cargo +/// 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 mut components = path.components().peekable(); + let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { + components.next(); + PathBuf::from(c.as_os_str()) + } else { + PathBuf::new() + }; + + for component in components { + match component { + Component::Prefix(..) => unreachable!(), + Component::RootDir => { + ret.push(component.as_os_str()); + } + Component::CurDir => {} + Component::ParentDir => { + ret.pop(); + } + Component::Normal(c) => { + ret.push(c); + } + } + } + ret +} + use helix_lsp::lsp; use url::Url; @@ -176,6 +212,20 @@ impl Document { } } + pub fn set_path(&mut self, path: &Path) -> Result<(), std::io::Error> { + // canonicalize path to absolute value + let current_dir = std::env::current_dir()?; + let path = normalize_path(¤t_dir.join(path)); + + if let Some(parent) = path.parent() { + // TODO: return error as necessary + if parent.exists() { + self.path = Some(path); + } + } + Ok(()) + } + pub fn set_language( &mut self, language_config: Option>, -- cgit v1.2.3-70-g09d2