Allow setting a filepath on :write

pull/19/head
Blaž Hrastnik 4 years ago
parent a2147fc7d5
commit ce25aa951e

@ -898,6 +898,12 @@ mod cmd {
fn write(editor: &mut Editor, args: &[&str], event: PromptEvent) { fn write(editor: &mut Editor, args: &[&str], event: PromptEvent) {
let (view, doc) = editor.current(); let (view, doc) = editor.current();
if let Some(path) = args.get(0) {
if let Err(err) = doc.set_path(Path::new(path)) {
editor.set_error(format!("invalid filepath: {}", err));
return;
};
}
if doc.path().is_none() { if doc.path().is_none() {
editor.set_error("cannot write a buffer without a filename".to_string()); editor.set_error("cannot write a buffer without a filename".to_string());
return; return;
@ -941,7 +947,7 @@ mod cmd {
Command { Command {
name: "write", name: "write",
alias: Some("w"), alias: Some("w"),
doc: "Write changes to disk.", doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",
fun: write, fun: write,
completer: Some(completers::filename), completer: Some(completers::filename),
}, },

@ -1,6 +1,6 @@
use anyhow::{Context, Error}; use anyhow::{Context, Error};
use std::future::Future; use std::future::Future;
use std::path::{Path, PathBuf}; use std::path::{Component, Path, PathBuf};
use std::sync::Arc; use std::sync::Arc;
use helix_core::{ 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 helix_lsp::lsp;
use url::Url; 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(&current_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( pub fn set_language(
&mut self, &mut self,
language_config: Option<Arc<helix_core::syntax::LanguageConfiguration>>, language_config: Option<Arc<helix_core::syntax::LanguageConfiguration>>,

Loading…
Cancel
Save