mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-22 02:50:19 +00:00
add query arg to envelope list command
This commit is contained in:
parent
c28b4c6bb3
commit
1e7adc5e0c
8 changed files with 88 additions and 40 deletions
|
@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Changed the `envelope list` options:
|
||||||
|
- the folder argument became a flag `--folder <name>`
|
||||||
|
- the query argument has been added at the end of the command to filter and sort results (only filter and IMAP for now)
|
||||||
|
|
||||||
## [1.0.0-beta.3] - 2024-02-25
|
## [1.0.0-beta.3] - 2024-02-25
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -159,6 +159,16 @@ version = "1.0.80"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
|
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ariadne"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "367fd0ad87307588d087544707bc5fbf4805ded96c7db922b70d368fa1cb5702"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
"yansi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-broadcast"
|
name = "async-broadcast"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -1209,13 +1219,13 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "email-lib"
|
name = "email-lib"
|
||||||
version = "0.22.3"
|
version = "0.22.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#79af9b0fa5fb30dcb1f8fbd322f7e40b9e05053a"
|
||||||
checksum = "7444aaa4ce80e796febd3def00dd27ec59f4097d65d727cfa5f16dfb07a4fd72"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"advisory-lock",
|
"advisory-lock",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"chumsky",
|
||||||
"convert_case",
|
"convert_case",
|
||||||
"dirs 4.0.0",
|
"dirs 4.0.0",
|
||||||
"email-macros",
|
"email-macros",
|
||||||
|
@ -1856,6 +1866,7 @@ name = "himalaya"
|
||||||
version = "1.0.0-beta.3"
|
version = "1.0.0-beta.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"ariadne",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -4956,6 +4967,12 @@ version = "0.8.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
|
checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yansi"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "z-base-32"
|
name = "z-base-32"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
|
|
@ -51,6 +51,7 @@ tempfile = "3.3"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
ariadne = "0.2"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
chrono = "0.4.24"
|
chrono = "0.4.24"
|
||||||
clap = { version = "4.4", features = ["derive"] }
|
clap = { version = "4.4", features = ["derive"] }
|
||||||
|
@ -88,3 +89,6 @@ uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
|
||||||
[target.'cfg(not(windows))'.dependencies.coredump]
|
[target.'cfg(not(windows))'.dependencies.coredump]
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
email-lib = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
||||||
|
|
|
@ -22,7 +22,12 @@ use email::{
|
||||||
backend::{
|
backend::{
|
||||||
feature::BackendFeature, macros::BackendContext, mapper::SomeBackendContextBuilderMapper,
|
feature::BackendFeature, macros::BackendContext, mapper::SomeBackendContextBuilderMapper,
|
||||||
},
|
},
|
||||||
envelope::{get::GetEnvelope, list::ListEnvelopes, watch::WatchEnvelopes, Id, SingleId},
|
envelope::{
|
||||||
|
get::GetEnvelope,
|
||||||
|
list::{ListEnvelopes, ListEnvelopesOptions},
|
||||||
|
watch::WatchEnvelopes,
|
||||||
|
Id, SingleId,
|
||||||
|
},
|
||||||
flag::{add::AddFlags, remove::RemoveFlags, set::SetFlags, Flag, Flags},
|
flag::{add::AddFlags, remove::RemoveFlags, set::SetFlags, Flag, Flags},
|
||||||
folder::{
|
folder::{
|
||||||
add::AddFolder, delete::DeleteFolder, expunge::ExpungeFolder, list::ListFolders,
|
add::AddFolder, delete::DeleteFolder, expunge::ExpungeFolder, list::ListFolders,
|
||||||
|
@ -644,12 +649,11 @@ impl Backend {
|
||||||
pub async fn list_envelopes(
|
pub async fn list_envelopes(
|
||||||
&self,
|
&self,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
page_size: usize,
|
opts: ListEnvelopesOptions,
|
||||||
page: usize,
|
|
||||||
) -> Result<Envelopes> {
|
) -> Result<Envelopes> {
|
||||||
let backend_kind = self.toml_account_config.list_envelopes_kind();
|
let backend_kind = self.toml_account_config.list_envelopes_kind();
|
||||||
let id_mapper = self.build_id_mapper(folder, backend_kind)?;
|
let id_mapper = self.build_id_mapper(folder, backend_kind)?;
|
||||||
let envelopes = self.backend.list_envelopes(folder, page_size, page).await?;
|
let envelopes = self.backend.list_envelopes(folder, opts).await?;
|
||||||
let envelopes = Envelopes::from_backend(&self.account_config, &id_mapper, envelopes)?;
|
let envelopes = Envelopes::from_backend(&self.account_config, &id_mapper, envelopes)?;
|
||||||
Ok(envelopes)
|
Ok(envelopes)
|
||||||
}
|
}
|
||||||
|
|
29
src/cache/args.rs
vendored
29
src/cache/args.rs
vendored
|
@ -1,29 +0,0 @@
|
||||||
//! This module provides arguments related to the cache.
|
|
||||||
|
|
||||||
use clap::{Arg, ArgAction, ArgMatches};
|
|
||||||
|
|
||||||
const ARG_DISABLE_CACHE: &str = "disable-cache";
|
|
||||||
|
|
||||||
/// Represents the disable cache flag argument. This argument allows
|
|
||||||
/// the user to disable any sort of cache.
|
|
||||||
pub fn global_args() -> impl IntoIterator<Item = Arg> {
|
|
||||||
[Arg::new(ARG_DISABLE_CACHE)
|
|
||||||
.help("Disable any sort of cache")
|
|
||||||
.long_help(
|
|
||||||
"Disable any sort of cache.
|
|
||||||
|
|
||||||
The action depends on commands it apply on. For example, when listing
|
|
||||||
envelopes using the IMAP backend, this flag will ensure that envelopes
|
|
||||||
are fetched from the IMAP server and not from the synchronized local
|
|
||||||
Maildir.",
|
|
||||||
)
|
|
||||||
.long("disable-cache")
|
|
||||||
.alias("no-cache")
|
|
||||||
.global(true)
|
|
||||||
.action(ArgAction::SetTrue)]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents the disable cache flag parser.
|
|
||||||
pub fn parse_disable_cache_arg(m: &ArgMatches) -> bool {
|
|
||||||
m.get_flag(ARG_DISABLE_CACHE)
|
|
||||||
}
|
|
1
src/cache/mod.rs
vendored
1
src/cache/mod.rs
vendored
|
@ -1,5 +1,4 @@
|
||||||
pub mod arg;
|
pub mod arg;
|
||||||
pub mod args;
|
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use dirs::data_dir;
|
use dirs::data_dir;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ariadne::{Color, Label, Report, ReportKind, Source};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use email::backend::feature::BackendFeatureSource;
|
use email::{backend::feature::BackendFeatureSource, envelope::list::ListEnvelopesOptions};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
#[cfg(feature = "account-sync")]
|
#[cfg(feature = "account-sync")]
|
||||||
|
@ -9,7 +10,7 @@ use crate::{
|
||||||
account::arg::name::AccountNameFlag,
|
account::arg::name::AccountNameFlag,
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
config::TomlConfig,
|
config::TomlConfig,
|
||||||
folder::arg::name::FolderNameOptionalArg,
|
folder::arg::name::FolderNameOptionalFlag,
|
||||||
printer::{PrintTableOpts, Printer},
|
printer::{PrintTableOpts, Printer},
|
||||||
ui::arg::max_width::TableMaxWidthFlag,
|
ui::arg::max_width::TableMaxWidthFlag,
|
||||||
};
|
};
|
||||||
|
@ -21,7 +22,7 @@ use crate::{
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct ListEnvelopesCommand {
|
pub struct ListEnvelopesCommand {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub folder: FolderNameOptionalArg,
|
pub folder: FolderNameOptionalFlag,
|
||||||
|
|
||||||
/// The page number.
|
/// The page number.
|
||||||
///
|
///
|
||||||
|
@ -45,6 +46,12 @@ pub struct ListEnvelopesCommand {
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub account: AccountNameFlag,
|
pub account: AccountNameFlag,
|
||||||
|
|
||||||
|
/// The list envelopes filter and sort query.
|
||||||
|
///
|
||||||
|
/// TODO
|
||||||
|
#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
|
||||||
|
pub query: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ListEnvelopesCommand {
|
impl Default for ListEnvelopesCommand {
|
||||||
|
@ -57,6 +64,7 @@ impl Default for ListEnvelopesCommand {
|
||||||
#[cfg(feature = "account-sync")]
|
#[cfg(feature = "account-sync")]
|
||||||
cache: Default::default(),
|
cache: Default::default(),
|
||||||
account: Default::default(),
|
account: Default::default(),
|
||||||
|
query: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +95,38 @@ impl ListEnvelopesCommand {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let envelopes = backend.list_envelopes(folder, page_size, page).await?;
|
let filter = match self.query.map(|filter| filter.join(" ").parse()) {
|
||||||
|
Some(Ok(filter)) => Some(filter),
|
||||||
|
Some(Err(err)) => {
|
||||||
|
if let email::envelope::list::Error::ParseFilterError(errs, query) = &err {
|
||||||
|
errs.into_iter().for_each(|e| {
|
||||||
|
Report::build(ReportKind::Error, "query", e.span().start)
|
||||||
|
.with_message(e.to_string())
|
||||||
|
.with_label(
|
||||||
|
Label::new(("query", e.span().into_range()))
|
||||||
|
.with_message(e.reason().to_string())
|
||||||
|
.with_color(Color::Red),
|
||||||
|
)
|
||||||
|
.finish()
|
||||||
|
.eprint(("query", Source::from(&query)))
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Err(err)?;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let opts = ListEnvelopesOptions {
|
||||||
|
page,
|
||||||
|
page_size,
|
||||||
|
filter,
|
||||||
|
sort: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let envelopes = backend.list_envelopes(folder, opts).await?;
|
||||||
|
|
||||||
printer.print_table(
|
printer.print_table(
|
||||||
Box::new(envelopes),
|
Box::new(envelopes),
|
||||||
|
|
|
@ -10,6 +10,14 @@ pub struct FolderNameOptionalFlag {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for FolderNameOptionalFlag {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: INBOX.to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The optional folder name argument parser.
|
/// The optional folder name argument parser.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct FolderNameOptionalArg {
|
pub struct FolderNameOptionalArg {
|
||||||
|
|
Loading…
Reference in a new issue