mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-21 18:40:19 +00:00
set up cli arg parser #15
This commit is contained in:
parent
2970828db9
commit
d8116c6103
5 changed files with 165 additions and 13 deletions
|
@ -13,9 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Populate Config struct from TOML [#2]
|
- Populate Config struct from TOML [#2]
|
||||||
- Set up IMAP connection [#3]
|
- Set up IMAP connection [#3]
|
||||||
- List new emails [#6]
|
- List new emails [#6]
|
||||||
|
- Set up CLI arg parser [#15]
|
||||||
|
|
||||||
[unreleased]: https://github.com/soywod/himalaya
|
[unreleased]: https://github.com/soywod/himalaya
|
||||||
|
|
||||||
[#1]: https://github.com/soywod/himalaya/issues/1
|
[#1]: https://github.com/soywod/himalaya/issues/1
|
||||||
[#2]: https://github.com/soywod/himalaya/issues/2
|
[#2]: https://github.com/soywod/himalaya/issues/2
|
||||||
[#3]: https://github.com/soywod/himalaya/issues/3
|
[#3]: https://github.com/soywod/himalaya/issues/3
|
||||||
|
[#15]: https://github.com/soywod/himalaya/issues/15
|
||||||
|
|
72
Cargo.lock
generated
72
Cargo.lock
generated
|
@ -9,12 +9,32 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -95,6 +115,21 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "2.33.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"atty",
|
||||||
|
"bitflags",
|
||||||
|
"strsim",
|
||||||
|
"textwrap",
|
||||||
|
"unicode-width",
|
||||||
|
"vec_map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
|
@ -146,10 +181,20 @@ dependencies = [
|
||||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "himalaya"
|
name = "himalaya"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"clap",
|
||||||
"imap",
|
"imap",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"rfc2047-decoder",
|
"rfc2047-decoder",
|
||||||
|
@ -489,6 +534,12 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.55"
|
version = "1.0.55"
|
||||||
|
@ -514,6 +565,15 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -543,6 +603,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -555,6 +621,12 @@ version = "0.2.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
|
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.2"
|
version = "0.9.2"
|
||||||
|
|
|
@ -6,6 +6,7 @@ authors = ["soywod <clement.douin@posteo.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
clap = "2.33.3"
|
||||||
imap = "2.4.0"
|
imap = "2.4.0"
|
||||||
native-tls = "0.2"
|
native-tls = "0.2"
|
||||||
rfc2047-decoder = "0.1.2"
|
rfc2047-decoder = "0.1.2"
|
||||||
|
|
17
src/imap.rs
17
src/imap.rs
|
@ -96,17 +96,14 @@ fn date_from_fetch(fetch: &imap::types::Fetch) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_new_emails(imap_sess: &mut ImapSession, mbox: &str) -> imap::Result<()> {
|
pub fn read_emails(imap_sess: &mut ImapSession, mbox: &str, query: &str) -> imap::Result<()> {
|
||||||
imap_sess.select(mbox)?;
|
imap_sess.select(mbox)?;
|
||||||
// let mboxes = imap_sess.list(Some(""), Some("*"))?;
|
|
||||||
// println!("Mboxes {:?}", mboxes);
|
|
||||||
|
|
||||||
let seqs = imap_sess
|
let seqs = imap_sess
|
||||||
.search("NOT SEEN")?
|
.search(query)?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|n| n.to_string())
|
.map(|n| n.to_string())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>();
|
||||||
.join(",");
|
|
||||||
|
|
||||||
let table_head = vec![
|
let table_head = vec![
|
||||||
table::Cell::new(
|
table::Cell::new(
|
||||||
|
@ -128,7 +125,10 @@ pub fn read_new_emails(imap_sess: &mut ImapSession, mbox: &str) -> imap::Result<
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut table_rows = imap_sess
|
let mut table_rows = imap_sess
|
||||||
.fetch(seqs, "(INTERNALDATE ENVELOPE)")?
|
.fetch(
|
||||||
|
seqs[..20.min(seqs.len())].join(","),
|
||||||
|
"(INTERNALDATE ENVELOPE)",
|
||||||
|
)?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|fetch| {
|
.map(|fetch| {
|
||||||
vec![
|
vec![
|
||||||
|
@ -146,3 +146,6 @@ pub fn read_new_emails(imap_sess: &mut ImapSession, mbox: &str) -> imap::Result<
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List mailboxes
|
||||||
|
// let mboxes = imap_sess.list(Some(""), Some("*"))?;
|
||||||
|
|
86
src/main.rs
86
src/main.rs
|
@ -2,16 +2,90 @@ mod config;
|
||||||
mod imap;
|
mod imap;
|
||||||
mod table;
|
mod table;
|
||||||
|
|
||||||
use std::env;
|
use clap::{App, Arg, SubCommand};
|
||||||
|
|
||||||
|
fn mailbox_arg() -> Arg<'static, 'static> {
|
||||||
|
Arg::with_name("mailbox")
|
||||||
|
.help("Name of the targeted mailbox")
|
||||||
|
.value_name("MAILBOX")
|
||||||
|
.required(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uid_arg() -> Arg<'static, 'static> {
|
||||||
|
Arg::with_name("uid")
|
||||||
|
.help("UID of the targeted email")
|
||||||
|
.value_name("UID")
|
||||||
|
.required(true)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mbox = env::args().nth(1).unwrap_or(String::from("inbox"));
|
|
||||||
let args = env::args().skip(2).collect::<Vec<_>>().join(" ").to_owned();
|
|
||||||
let config = config::read_file();
|
let config = config::read_file();
|
||||||
let mut imap_sess = imap::login(&config);
|
let mut imap_sess = imap::login(&config);
|
||||||
|
|
||||||
match args.as_str() {
|
let matches = App::new("Himalaya")
|
||||||
"read new" => imap::read_new_emails(&mut imap_sess, &mbox).unwrap(),
|
.version("0.1.0")
|
||||||
_ => println!("Himalaya: command not found e"),
|
.about("📫 Minimalist CLI mail client")
|
||||||
|
.author("soywod <clement.douin@posteo.net>")
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("read")
|
||||||
|
.about("Reads an email by its UID")
|
||||||
|
.arg(mailbox_arg())
|
||||||
|
.arg(uid_arg()),
|
||||||
|
)
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("query")
|
||||||
|
.about("Prints emails filtered by the given IMAP query")
|
||||||
|
.arg(mailbox_arg())
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("query")
|
||||||
|
.help("IMAP query (see https://tools.ietf.org/html/rfc3501#section-6.4.4)")
|
||||||
|
.value_name("COMMANDS")
|
||||||
|
.multiple(true)
|
||||||
|
.required(true),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.subcommand(SubCommand::with_name("write").about("Writes a new email"))
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("forward")
|
||||||
|
.about("Forwards an email by its UID")
|
||||||
|
.arg(mailbox_arg())
|
||||||
|
.arg(uid_arg()),
|
||||||
|
)
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("reply")
|
||||||
|
.about("Replies to an email by its UID")
|
||||||
|
.arg(mailbox_arg())
|
||||||
|
.arg(uid_arg())
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("reply all")
|
||||||
|
.help("Replies to all recipients")
|
||||||
|
.short("a")
|
||||||
|
.long("all"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
|
if let Some(matches) = matches.subcommand_matches("query") {
|
||||||
|
let mbox = matches.value_of("mailbox").unwrap_or("inbox");
|
||||||
|
|
||||||
|
if let Some(matches) = matches.values_of("query") {
|
||||||
|
let query = matches
|
||||||
|
.fold((false, vec![]), |(escape, mut cmds), cmd| {
|
||||||
|
if ["subject", "body", "text"].contains(&cmd.to_lowercase().as_str()) {
|
||||||
|
cmds.push(cmd.to_string());
|
||||||
|
(true, cmds)
|
||||||
|
} else if escape {
|
||||||
|
cmds.push(format!("\"{}\"", cmd));
|
||||||
|
(false, cmds)
|
||||||
|
} else {
|
||||||
|
cmds.push(cmd.to_string());
|
||||||
|
(false, cmds)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.1
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
imap::read_emails(&mut imap_sess, &mbox, &query).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue