improve choice after editing msg

This commit is contained in:
Clément DOUIN 2021-03-16 23:39:43 +01:00
parent 0dd73e693e
commit 64019fa5ec
No known key found for this signature in database
GPG key ID: 69C9B9CFFDEE2DEF
3 changed files with 122 additions and 34 deletions

View file

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- IDLE support [#29] - IDLE support [#29]
- Improve choice after editing msg [#30]
### Changed ### Changed
@ -80,6 +81,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#22]: https://github.com/soywod/himalaya/issues/22 [#22]: https://github.com/soywod/himalaya/issues/22
[#25]: https://github.com/soywod/himalaya/issues/25 [#25]: https://github.com/soywod/himalaya/issues/25
[#29]: https://github.com/soywod/himalaya/issues/29 [#29]: https://github.com/soywod/himalaya/issues/29
[#30]: https://github.com/soywod/himalaya/issues/30
[#32]: https://github.com/soywod/himalaya/issues/32 [#32]: https://github.com/soywod/himalaya/issues/32
[#38]: https://github.com/soywod/himalaya/issues/38 [#38]: https://github.com/soywod/himalaya/issues/38
[#39]: https://github.com/soywod/himalaya/issues/39 [#39]: https://github.com/soywod/himalaya/issues/39

View file

@ -1,6 +1,6 @@
use clap::{self, Arg, SubCommand}; use clap::{self, Arg, SubCommand};
use error_chain::error_chain; use error_chain::error_chain;
use std::fs; use std::{env, fs};
use crate::{ use crate::{
config::{self, Config}, config::{self, Config},
@ -332,14 +332,33 @@ impl<'a> App<'a> {
let mut imap_conn = ImapConnector::new(&account)?; let mut imap_conn = ImapConnector::new(&account)?;
let tpl = Msg::build_new_tpl(&config, &account)?; let tpl = Msg::build_new_tpl(&config, &account)?;
let content = input::open_editor_with_tpl(tpl.to_string().as_bytes())?; let content = input::open_editor_with_tpl(tpl.to_string().as_bytes())?;
let msg = Msg::from(content); let mut msg = Msg::from(content);
input::ask_for_confirmation("Send the message?")?; loop {
match input::post_edit_choice() {
println!("Sending…"); Ok(choice) => match choice {
smtp::send(&account, &msg.to_sendable_msg()?)?; input::Choice::Send => {
imap_conn.append_msg("Sent", &msg.to_vec()?)?; println!("Sending…");
println!("Done!"); smtp::send(&account, &msg.to_sendable_msg()?)?;
imap_conn.append_msg("Sent", &msg.to_vec()?)?;
println!("Done!");
break;
}
input::Choice::Draft => {
println!("Saving to draft…");
imap_conn.append_msg("Drafts", &msg.to_vec()?)?;
println!("Done!");
break;
}
input::Choice::Edit => {
let content = input::open_editor_with_draft()?;
msg = Msg::from(content);
}
input::Choice::Quit => break,
},
Err(err) => eprintln!("{}", err),
}
}
imap_conn.logout(); imap_conn.logout();
} }
@ -395,14 +414,33 @@ impl<'a> App<'a> {
}; };
let content = input::open_editor_with_tpl(&tpl.to_string().as_bytes())?; let content = input::open_editor_with_tpl(&tpl.to_string().as_bytes())?;
let msg = Msg::from(content); let mut msg = Msg::from(content);
input::ask_for_confirmation("Send the message?")?; loop {
match input::post_edit_choice() {
println!("Sending…"); Ok(choice) => match choice {
smtp::send(&account, &msg.to_sendable_msg()?)?; input::Choice::Send => {
imap_conn.append_msg("Sent", &msg.to_vec()?)?; println!("Sending…");
println!("Done!"); smtp::send(&account, &msg.to_sendable_msg()?)?;
imap_conn.append_msg("Sent", &msg.to_vec()?)?;
println!("Done!");
break;
}
input::Choice::Draft => {
println!("Saving to draft…");
imap_conn.append_msg("Drafts", &msg.to_vec()?)?;
println!("Done!");
break;
}
input::Choice::Edit => {
let content = input::open_editor_with_draft()?;
msg = Msg::from(content);
}
input::Choice::Quit => break,
},
Err(err) => eprintln!("{}", err),
}
}
imap_conn.logout(); imap_conn.logout();
} }
@ -418,14 +456,33 @@ impl<'a> App<'a> {
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?); let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
let tpl = msg.build_forward_tpl(&config, &account)?; let tpl = msg.build_forward_tpl(&config, &account)?;
let content = input::open_editor_with_tpl(&tpl.to_string().as_bytes())?; let content = input::open_editor_with_tpl(&tpl.to_string().as_bytes())?;
let msg = Msg::from(content); let mut msg = Msg::from(content);
input::ask_for_confirmation("Send the message?")?; loop {
match input::post_edit_choice() {
println!("Sending…"); Ok(choice) => match choice {
smtp::send(&account, &msg.to_sendable_msg()?)?; input::Choice::Send => {
imap_conn.append_msg("Sent", &msg.to_vec()?)?; println!("Sending…");
println!("Done!"); smtp::send(&account, &msg.to_sendable_msg()?)?;
imap_conn.append_msg("Sent", &msg.to_vec()?)?;
println!("Done!");
break;
}
input::Choice::Draft => {
println!("Saving to draft…");
imap_conn.append_msg("Drafts", &msg.to_vec()?)?;
println!("Done!");
break;
}
input::Choice::Edit => {
let content = input::open_editor_with_draft()?;
msg = Msg::from(content);
}
input::Choice::Quit => break,
},
Err(err) => eprintln!("{}", err),
}
}
imap_conn.logout(); imap_conn.logout();
} }

View file

@ -1,7 +1,7 @@
use error_chain::error_chain; use error_chain::error_chain;
use std::{ use std::{
env, env,
fs::{remove_file, File}, fs::File,
io::{self, Read, Write}, io::{self, Read, Write},
process::Command, process::Command,
}; };
@ -29,23 +29,52 @@ pub fn open_editor_with_tpl(tpl: &[u8]) -> Result<String> {
.chain_err(|| format!("Cannot open file `{}`", draft_path.to_string_lossy()))? .chain_err(|| format!("Cannot open file `{}`", draft_path.to_string_lossy()))?
.read_to_string(&mut draft) .read_to_string(&mut draft)
.chain_err(|| format!("Cannot read file `{}`", draft_path.to_string_lossy()))?; .chain_err(|| format!("Cannot read file `{}`", draft_path.to_string_lossy()))?;
remove_file(&draft_path)
.chain_err(|| format!("Cannot remove file `{}`", draft_path.to_string_lossy()))?;
Ok(draft) Ok(draft)
} }
pub fn ask_for_confirmation(prompt: &str) -> Result<()> { pub fn open_editor_with_draft() -> Result<String> {
print!("{} (y/n) ", prompt); // Creates draft file
let mut draft_path = env::temp_dir();
draft_path.push("himalaya-draft.mail");
// Opens editor and saves user input to draft file
Command::new(env::var("EDITOR").chain_err(|| "Cannot find `EDITOR` env var")?)
.arg(&draft_path)
.status()
.chain_err(|| "Cannot start editor")?;
// Extracts draft file content
let mut draft = String::new();
File::open(&draft_path)
.chain_err(|| format!("Cannot open file `{}`", draft_path.to_string_lossy()))?
.read_to_string(&mut draft)
.chain_err(|| format!("Cannot read file `{}`", draft_path.to_string_lossy()))?;
Ok(draft)
}
pub enum Choice {
Send,
Draft,
Edit,
Quit,
}
pub fn post_edit_choice() -> Result<Choice> {
print!("(s)end, (d)raft, (e)dit or (q)uit? ");
io::stdout().flush().chain_err(|| "Cannot flush stdout")?; io::stdout().flush().chain_err(|| "Cannot flush stdout")?;
match io::stdin() let mut buf = String::new();
.bytes() io::stdin()
.next() .read_line(&mut buf)
.and_then(|res| res.ok()) .chain_err(|| "Cannot read stdin")?;
.map(|bytes| bytes as char)
{ match buf.bytes().next().map(|bytes| bytes as char) {
Some('y') | Some('Y') => Ok(()), Some('s') => Ok(Choice::Send),
Some('d') => Ok(Choice::Draft),
Some('e') => Ok(Choice::Edit),
Some('q') => Ok(Choice::Quit),
Some(choice) => Err(format!("Invalid choice `{}`", choice).into()), Some(choice) => Err(format!("Invalid choice `{}`", choice).into()),
None => Err("Empty choice".into()), None => Err("Empty choice".into()),
} }