init editor, improve main error management

This commit is contained in:
Clément DOUIN 2021-01-07 00:19:07 +01:00
parent c7b326a695
commit d746a780ba
No known key found for this signature in database
GPG key ID: 69C9B9CFFDEE2DEF
2 changed files with 114 additions and 67 deletions

62
src/editor.rs Normal file
View file

@ -0,0 +1,62 @@
use std::env::temp_dir;
use std::fs::{remove_file, File};
use std::io::{self, Read, Write};
use std::process::Command;
use std::{error, fmt, result};
// Error wrapper
#[derive(Debug)]
pub enum Error {
IoError(io::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::IoError(err) => err.fmt(f),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
Error::IoError(ref err) => Some(err),
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error::IoError(err)
}
}
// Result wrapper
type Result<T> = result::Result<T, Error>;
// Utils
fn open_with_template(template: &[u8]) -> Result<String> {
// Create temporary draft
let mut draft_path = temp_dir();
draft_path.push("himalaya-draft.mail");
File::create(&draft_path)?.write(template)?;
// Open editor and save user input to draft
Command::new(env!("EDITOR")).arg(&draft_path).status()?;
// Read draft
let mut draft = String::new();
File::open(&draft_path)?.read_to_string(&mut draft)?;
remove_file(&draft_path)?;
Ok(draft)
}
pub fn open_with_new_template() -> Result<String> {
let template = ["To: ", "Subject: ", ""].join("\r\n");
open_with_template(template.as_bytes())
}

View file

@ -1,4 +1,5 @@
mod config;
mod editor;
mod email;
mod imap;
mod mailbox;
@ -6,29 +7,53 @@ mod smtp;
mod table;
use clap::{App, Arg, SubCommand};
use std::env::temp_dir;
use std::fs::{remove_file, File};
use std::io::{Read, Write};
use std::process::{exit, Command};
use std::{error, fmt, process::exit, result};
use crate::config::Config;
use crate::imap::ImapConnector;
use crate::table::DisplayTable;
fn main() {
if let Err(err) = dispatch() {
eprintln!("Error: {}", err);
exit(1);
#[derive(Debug)]
pub enum Error {
EditorError(editor::Error),
ImapError(imap::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::EditorError(err) => err.fmt(f),
Error::ImapError(err) => err.fmt(f),
}
}
}
fn new_email_tpl() -> String {
["To: ", "Subject: ", ""].join("\r\n")
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
Error::EditorError(ref err) => Some(err),
Error::ImapError(ref err) => Some(err),
}
}
}
// fn forward_email_tpl() -> String {
// ["To: ", "Subject: ", ""].join("\r\n")
// }
impl From<editor::Error> for Error {
fn from(err: editor::Error) -> Error {
Error::EditorError(err)
}
}
impl From<imap::Error> for Error {
fn from(err: imap::Error) -> Error {
Error::ImapError(err)
}
}
// Result wrapper
type Result<T> = result::Result<T, Error>;
// Run
fn mailbox_arg() -> Arg<'static, 'static> {
Arg::with_name("mailbox")
@ -46,7 +71,7 @@ fn uid_arg() -> Arg<'static, 'static> {
.required(true)
}
fn dispatch() -> Result<(), imap::Error> {
fn run() -> Result<()> {
let matches = App::new("Himalaya")
.version("0.1.0")
.about("📫 Minimalist CLI email client")
@ -117,12 +142,12 @@ fn dispatch() -> Result<(), imap::Error> {
let query = matches
.fold((false, vec![]), |(escape, mut cmds), cmd| {
match (cmd, escape) {
// Next command needs to be escaped
// Next command is an arg and needs to be escaped
("subject", _) | ("body", _) | ("text", _) => {
cmds.push(cmd.to_string());
(true, cmds)
}
// Escaped commands
// Escaped arg commands
(_, true) => {
cmds.push(format!("\"{}\"", cmd));
(false, cmds)
@ -157,59 +182,19 @@ fn dispatch() -> Result<(), imap::Error> {
if let Some(_) = matches.subcommand_matches("write") {
let config = Config::new_from_file();
let draft = editor::open_with_new_template()?;
let mut draft_path = temp_dir();
draft_path.push("himalaya-draft.mail");
File::create(&draft_path)
.expect("Could not create draft file")
.write(new_email_tpl().as_bytes())
.expect("Could not write into draft file");
Command::new(env!("EDITOR"))
.arg(&draft_path)
.status()
.expect("Could not start $EDITOR");
let mut draft = String::new();
File::open(&draft_path)
.expect("Could not open draft file")
.read_to_string(&mut draft)
.expect("Could not read draft file");
remove_file(&draft_path).expect("Could not remove draft file");
smtp::send(&config, &draft.as_bytes());
smtp::send(&config, draft.as_bytes());
}
// if let Some(_) = matches.subcommand_matches("forward") {
// let config = Config::new_from_file();
// let mbox = matches.value_of("mailbox").unwrap();
// let uid = matches.value_of("uid").unwrap();
// let mut draft_path = temp_dir();
// draft_path.push("himalaya-draft.mail");
// File::create(&draft_path)
// .expect("Could not create draft file")
// .write(forward_email_tpl().as_bytes())
// .expect("Could not write into draft file");
// Command::new(env!("EDITOR"))
// .arg(&draft_path)
// .status()
// .expect("Could not start $EDITOR");
// let mut draft = String::new();
// File::open(&draft_path)
// .expect("Could not open draft file")
// .read_to_string(&mut draft)
// .expect("Could not read draft file");
// remove_file(&draft_path).expect("Could not remove draft file");
// smtp::send(&config, &draft.as_bytes());
// }
Ok(())
}
// Main
fn main() {
if let Err(err) = run() {
eprintln!("Error: {}", err);
exit(1);
}
}