Skip to content

Commit

Permalink
wip: add message thread command
Browse files Browse the repository at this point in the history
  • Loading branch information
soywod committed May 22, 2024
1 parent 2eff215 commit 6cbfc57
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 124 deletions.
18 changes: 17 additions & 1 deletion src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pub(crate) mod wizard;

use async_trait::async_trait;
use color_eyre::Result;
use petgraph::graphmap::DiGraphMap;
use std::{fmt::Display, ops::Deref, sync::Arc};

#[cfg(feature = "imap")]
Expand Down Expand Up @@ -719,6 +718,23 @@ impl Backend {
Ok(envelopes)
}

pub async fn thread_envelope(
&self,
folder: &str,
id: usize,
opts: ListEnvelopesOptions,
) -> Result<ThreadedEnvelopes> {
let backend_kind = self.toml_account_config.thread_envelopes_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?;
let envelopes = self
.backend
.thread_envelope(folder, SingleId::from(id), opts)
.await?;
// let envelopes =
// Envelopes::from_backend(&self.backend.account_config, &id_mapper, envelopes)?;
Ok(envelopes)
}

pub async fn add_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> {
let backend_kind = self.toml_account_config.add_flags_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?;
Expand Down
136 changes: 15 additions & 121 deletions src/email/envelope/command/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,18 @@ use clap::Parser;
use color_eyre::Result;
use crossterm::{
cursor::{self, MoveToColumn},
style::{Attribute, Color, Print, ResetColor, SetAttribute, SetForegroundColor},
style::{Color, Print, ResetColor, SetForegroundColor},
terminal, ExecutableCommand,
};
use email::{
account::config::AccountConfig,
backend::feature::BackendFeatureSource,
email::search_query,
envelope::{list::ListEnvelopesOptions, ThreadedEnvelope},
search_query::{filter::SearchEmailsFilterQuery, SearchEmailsQuery},
};
use petgraph::{graphmap::DiGraphMap, visit::IntoNodeIdentifiers, Direction};
use std::{
collections::{HashMap, HashSet},
io::Write,
process::exit,
search_query::SearchEmailsQuery,
};
use petgraph::graphmap::DiGraphMap;
use std::{io::Write, process::exit};
use tracing::info;

#[cfg(feature = "account-sync")]
Expand All @@ -37,123 +33,23 @@ pub struct ThreadEnvelopesCommand {
#[command(flatten)]
pub folder: FolderNameOptionalFlag,

/// The page number.
///
/// The page number starts from 1 (which is the default). Giving a
/// page number to big will result in a out of bound error.
#[arg(long, short, value_name = "NUMBER", default_value = "1")]
pub page: usize,

/// The page size.
///
/// Determine the amount of envelopes a page should contain.
#[arg(long, short = 's', value_name = "NUMBER")]
pub page_size: Option<usize>,

#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,

#[command(flatten)]
pub account: AccountNameFlag,

/// The maximum width the table should not exceed.
///
/// This argument will force the table not to exceed the given
/// width in pixels. Columns may shrink with ellipsis in order to
/// fit the width.
#[arg(long = "max-width", short = 'w')]
#[arg(name = "table_max_width", value_name = "PIXELS")]
pub table_max_width: Option<u16>,

/// The thread envelopes filter and sort query.
///
/// The query can be a filter query, a sort query or both
/// together.
///
/// A filter query is composed of operators and conditions. There
/// is 3 operators and 8 conditions:
///
/// • not <condition> → filter envelopes that do not match the
/// condition
///
/// • <condition> and <condition> → filter envelopes that match
/// both conditions
///
/// • <condition> or <condition> → filter envelopes that match
/// one of the conditions
///
/// ◦ date <yyyy-mm-dd> → filter envelopes that match the given
/// date
///
/// ◦ before <yyyy-mm-dd> → filter envelopes with date strictly
/// before the given one
///
/// ◦ after <yyyy-mm-dd> → filter envelopes with date stricly
/// after the given one
///
/// ◦ from <pattern> → filter envelopes with senders matching the
/// given pattern
///
/// ◦ to <pattern> → filter envelopes with recipients matching
/// the given pattern
///
/// ◦ subject <pattern> → filter envelopes with subject matching
/// the given pattern
///
/// ◦ body <pattern> → filter envelopes with text bodies matching
/// the given pattern
///
/// ◦ flag <flag> → filter envelopes matching the given flag
///
/// A sort query starts by "order by", and is composed of kinds
/// and orders. There is 4 kinds and 2 orders:
///
/// • date [order] → sort envelopes by date
///
/// • from [order] → sort envelopes by sender
///
/// • to [order] → sort envelopes by recipient
///
/// • subject [order] → sort envelopes by subject
///
/// ◦ <kind> asc → sort envelopes by the given kind in ascending
/// order
///
/// ◦ <kind> desc → sort envelopes by the given kind in
/// descending order
///
/// Examples:
///
/// subject foo and body bar → filter envelopes containing "foo"
/// in their subject and "bar" in their text bodies
///
/// order by date desc subject → sort envelopes by descending date
/// (most recent first), then by ascending subject
///
/// subject foo and body bar order by date desc subject →
/// combination of the 2 previous examples
/// Show only threads that contain the given envelope identifier.
#[arg(long, short)]
pub id: Option<usize>,

#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
pub query: Option<Vec<String>>,
}

impl Default for ThreadEnvelopesCommand {
fn default() -> Self {
Self {
folder: Default::default(),
page: 1,
page_size: Default::default(),
#[cfg(feature = "account-sync")]
cache: Default::default(),
account: Default::default(),
query: Default::default(),
table_max_width: Default::default(),
}
}
}

impl ThreadEnvelopesCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
pub async fn execute(self, _printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing thread envelopes command");

let (toml_account_config, account_config) = config.clone().into_account_configs(
Expand All @@ -163,11 +59,6 @@ impl ThreadEnvelopesCommand {
)?;

let folder = &self.folder.name;
let page = 1.max(self.page) - 1;
let page_size = self
.page_size
.unwrap_or_else(|| account_config.get_envelope_thread_page_size());

let thread_envelopes_kind = toml_account_config.thread_envelopes_kind();

let backend = Backend::new(
Expand Down Expand Up @@ -205,12 +96,15 @@ impl ThreadEnvelopesCommand {
};

let opts = ListEnvelopesOptions {
page,
page_size,
page: 0,
page_size: 0,
query,
};

let envelopes = backend.thread_envelopes(folder, opts).await?;
let envelopes = match self.id {
Some(id) => backend.thread_envelope(folder, id, opts).await,
None => backend.thread_envelopes(folder, opts).await,
}?;

let mut stdout = std::io::stdout();
write_tree(
Expand Down
9 changes: 7 additions & 2 deletions src/email/message/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@ pub mod read;
pub mod reply;
pub mod save;
pub mod send;
pub mod thread;
pub mod write;

use color_eyre::Result;
use clap::Subcommand;
use color_eyre::Result;

use crate::{config::TomlConfig, printer::Printer};

use self::{
copy::MessageCopyCommand, delete::MessageDeleteCommand, forward::MessageForwardCommand,
mailto::MessageMailtoCommand, r#move::MessageMoveCommand, read::MessageReadCommand,
reply::MessageReplyCommand, save::MessageSaveCommand, send::MessageSendCommand,
write::MessageWriteCommand,
thread::MessageThreadCommand, write::MessageWriteCommand,
};

/// Manage messages.
Expand All @@ -32,6 +33,9 @@ pub enum MessageSubcommand {
#[command(arg_required_else_help = true)]
Read(MessageReadCommand),

#[command(arg_required_else_help = true)]
Thread(MessageThreadCommand),

#[command(aliases = ["add", "create", "new", "compose"])]
Write(MessageWriteCommand),

Expand Down Expand Up @@ -66,6 +70,7 @@ impl MessageSubcommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self {
Self::Read(cmd) => cmd.execute(printer, config).await,
Self::Thread(cmd) => cmd.execute(printer, config).await,
Self::Write(cmd) => cmd.execute(printer, config).await,
Self::Reply(cmd) => cmd.execute(printer, config).await,
Self::Forward(cmd) => cmd.execute(printer, config).await,
Expand Down
Loading

0 comments on commit 6cbfc57

Please sign in to comment.