Skip to content

Instantly share code, notes, and snippets.

@rolandshoemaker
Created December 28, 2014 17:35
Show Gist options
  • Save rolandshoemaker/8b81caeae559a51d770e to your computer and use it in GitHub Desktop.
Save rolandshoemaker/8b81caeae559a51d770e to your computer and use it in GitHub Desktop.
Drop to $VISUAL or $EDITOR to edit a String in rust (via temporary file)
extern crate libc;
use std::io::{File, Open, ReadWrite, TempDir, Command, SeekSet};
use std::io::process::{InheritFd};
use std::os;
pub use self::libc::{
STDIN_FILENO,
STDOUT_FILENO,
STDERR_FILENO
};
fn temporary_editor(contents: String) -> String {
// setup temporary directory
let tmpdir = match TempDir::new("tempplace") {
Ok(dir) => dir,
Err(e) => panic!("couldn't create temporary directory: {}", e)
};
// setup temporary file to write/read
let tmppath = tmpdir.path().join("something-unique");
let mut tmpfile = match File::open_mode(&tmppath, Open, ReadWrite) {
Ok(f) => f,
Err(e) => panic!("File error: {}", e)
};
tmpfile.write_line(contents.as_slice()).ok().expect("Failed to write line to temp file");
// we now have a temp file, at `tmppath`, that contains `contents`
// first we need to know which one
let editor = match os::getenv("VISUAL") {
Some(val) => val,
None => {
match os::getenv("EDITOR") {
Some(val) => val,
None => panic!("Neither $VISUAL nor $EDITOR is set.")
}
}
};
// lets start `editor` and edit the file at `tmppath`
// first we need to set STDIN, STDOUT, and STDERR to those that theca is
// currently using so we can display the editor
let mut editor_command = Command::new(editor);
editor_command.arg(tmppath.display().to_string());
editor_command.stdin(InheritFd(libc::STDIN_FILENO));
editor_command.stdout(InheritFd(libc::STDOUT_FILENO));
editor_command.stderr(InheritFd(libc::STDERR_FILENO));
let editor_proc = editor_command.spawn();
match editor_proc.ok().expect("Couldn't launch editor").wait().is_ok() {
true => {
// finished editing, time to read `tmpfile` for the final output
// seek to start of `tmpfile`
tmpfile.seek(0, SeekSet).ok().expect("Can't seek to start of temp file");
tmpfile.read_to_string().unwrap()
}
false => panic!("The editor broke")
}
}
fn main() {
let test = temporary_editor("this totes works".to_string());
println!("temp file contained: {}", test);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment