pueue/client/edit.rs
2020-05-13 20:31:40 +02:00

67 lines
2 KiB
Rust

use ::std::env;
use ::std::io::{Read, Seek, SeekFrom, Write};
use ::std::process::Command;
use ::tempfile::NamedTempFile;
use ::pueue::message::*;
use crate::cli::SubCommand;
/// This function allows the user to edit a task's command or path.
/// Save the string to a temporary file, which is the edited by the user with $EDITOR.
/// As soon as the editor is closed, read the file content and return the
/// final edit message with the updated command to the daemon.
pub fn edit(message: EditResponseMessage, cli_command: &SubCommand) -> Message {
let edit_path = match cli_command {
SubCommand::Edit { path, .. } => *path,
_ => panic!(
"Got wrong Subcommand {:?} in edit. This shouldn't happen",
cli_command
),
};
let mut command = message.command;
let mut path = message.path;
let mut to_edit = if edit_path {
path.clone()
} else {
command.clone()
};
// Create a temporary file with the command so we can edit it with the editor.
let mut file = NamedTempFile::new().expect("Failed to create a temporary file");
writeln!(file, "{}", to_edit).expect("Failed writing to temporary file");
// Start the editor on this file.
let editor = &env::var("EDITOR").unwrap_or_else(|_e| "vi".to_string());
Command::new(editor)
.arg(file.path())
.status()
.expect("Failed to start editor. Do you have the $EDITOR environment variable set?");
// Read the file.
let mut file = file.into_file();
file.seek(SeekFrom::Start(0))
.expect("Couldn't seek to start of file. Aborting.");
to_edit = String::new();
file.read_to_string(&mut to_edit)
.expect("Failed to read Command after editing");
// Remove any trailing newlines from the command.
while to_edit.ends_with('\n') || to_edit.ends_with('\r') {
to_edit.pop();
}
if edit_path {
path = to_edit
} else {
command = to_edit
}
Message::Edit(EditMessage {
task_id: message.task_id,
command,
path,
})
}