add mailbox attributes (#134)

This commit is contained in:
Clément DOUIN 2021-05-04 23:11:01 +02:00
parent 435932a501
commit dcbbe01c94
No known key found for this signature in database
GPG key ID: 69C9B9CFFDEE2DEF
4 changed files with 107 additions and 28 deletions

View file

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Mailbox attributes [#134]
### Changed
- Get signature from file [#135]
@ -243,6 +247,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#131]: https://github.com/soywod/himalaya/issues/131
[#132]: https://github.com/soywod/himalaya/issues/132
[#133]: https://github.com/soywod/himalaya/issues/133
[#134]: https://github.com/soywod/himalaya/issues/134
[#135]: https://github.com/soywod/himalaya/issues/135
[#136]: https://github.com/soywod/himalaya/issues/136
[#138]: https://github.com/soywod/himalaya/issues/138

View file

@ -7,7 +7,6 @@ use std::{collections::HashSet, iter::FromIterator, net::TcpStream};
use crate::{
config::model::{Account, Config},
flag::model::Flag,
mbox::model::{Mbox, Mboxes},
msg::model::Msg,
};
@ -167,16 +166,13 @@ impl<'ic> ImapConnector<'ic> {
}
}
pub fn list_mboxes(&mut self) -> Result<Mboxes> {
let mboxes = self
pub fn list_mboxes(&mut self) -> Result<imap::types::ZeroCopy<Vec<imap::types::Name>>> {
let names = self
.sess
.list(Some(""), Some("*"))
.chain_err(|| "Cannot list mailboxes")?
.iter()
.map(Mbox::from_name)
.collect::<Vec<_>>();
.chain_err(|| "Cannot list mailboxes")?;
Ok(Mboxes(mboxes))
Ok(names)
}
pub fn list_msgs(

View file

@ -2,7 +2,7 @@ use clap;
use error_chain::error_chain;
use log::{debug, trace};
use crate::{app::App, imap::model::ImapConnector};
use crate::{app::App, imap::model::ImapConnector, mbox::model::Mboxes};
error_chain! {
links {
@ -36,7 +36,8 @@ pub fn mbox_matches(app: &App) -> Result<bool> {
debug!("mailboxes command matched");
let mut imap_conn = ImapConnector::new(&app.account)?;
let mboxes = imap_conn.list_mboxes()?;
let names = imap_conn.list_mboxes()?;
let mboxes = Mboxes::from(&names);
debug!("found {} mailboxes", mboxes.0.len());
trace!("mailboxes: {:?}", mboxes);
app.output.print(mboxes);

View file

@ -1,29 +1,100 @@
use imap;
use serde::Serialize;
use serde::{
ser::{self, SerializeSeq},
Serialize,
};
use std::fmt;
use crate::table::{Cell, Row, Table};
// Mbox
// Attribute
#[derive(Debug, Serialize)]
pub struct Mbox {
pub delim: String,
pub name: String,
pub attributes: Vec<String>,
}
#[derive(Debug, PartialEq)]
struct SerializableAttribute<'a>(&'a imap::types::NameAttribute<'a>);
impl Mbox {
pub fn from_name(name: &imap::types::Name) -> Self {
Self {
delim: name.delimiter().unwrap_or_default().to_owned(),
name: name.name().to_owned(),
attributes: vec![], // TODO: set attributes
impl<'a> Into<&'a str> for &'a SerializableAttribute<'a> {
fn into(self) -> &'a str {
match &self.0 {
imap::types::NameAttribute::NoInferiors => "\\NoInferiors",
imap::types::NameAttribute::NoSelect => "\\NoSelect",
imap::types::NameAttribute::Marked => "\\Marked",
imap::types::NameAttribute::Unmarked => "\\Unmarked",
imap::types::NameAttribute::Custom(cow) => cow,
}
}
}
impl Table for Mbox {
impl<'a> ser::Serialize for SerializableAttribute<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(self.into())
}
}
#[derive(Debug, PartialEq)]
pub struct Attributes<'a>(&'a [imap::types::NameAttribute<'a>]);
impl<'a> From<&'a [imap::types::NameAttribute<'a>]> for Attributes<'a> {
fn from(attrs: &'a [imap::types::NameAttribute<'a>]) -> Self {
Self(attrs)
}
}
impl<'a> ToString for Attributes<'a> {
fn to_string(&self) -> String {
match self.0.len() {
0 => String::new(),
1 => {
let attr = &SerializableAttribute(&self.0[0]);
let attr: &str = attr.into();
attr.to_owned()
}
_ => {
let attr = &SerializableAttribute(&self.0[0]);
let attr: &str = attr.into();
format!("{}, {}", attr, Attributes(&self.0[1..]).to_string())
}
}
}
}
impl<'a> ser::Serialize for Attributes<'a> {
fn serialize<T>(&self, serializer: T) -> Result<T::Ok, T::Error>
where
T: ser::Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
for attr in self.0 {
seq.serialize_element(&SerializableAttribute(attr))?;
}
seq.end()
}
}
// Mailbox
#[derive(Debug, Serialize)]
pub struct Mbox<'a> {
pub delim: String,
pub name: String,
pub attributes: Attributes<'a>,
}
impl<'a> From<&'a imap::types::Name> for Mbox<'a> {
fn from(name: &'a imap::types::Name) -> Self {
Self {
delim: name.delimiter().unwrap_or_default().to_owned(),
name: name.name().to_owned(),
attributes: Attributes::from(name.attributes()),
}
}
}
impl<'a> Table for Mbox<'a> {
fn head() -> Row {
Row::new()
.cell(Cell::new("DELIM").bold().underline().white())
@ -41,16 +112,22 @@ impl Table for Mbox {
Row::new()
.cell(Cell::new(&self.delim).white())
.cell(Cell::new(&self.name).green())
.cell(Cell::new(&self.attributes.join(", ")).shrinkable().yellow())
.cell(Cell::new(&self.attributes.to_string()).shrinkable().blue())
}
}
// Mboxes
#[derive(Debug, Serialize)]
pub struct Mboxes(pub Vec<Mbox>);
pub struct Mboxes<'a>(pub Vec<Mbox<'a>>);
impl fmt::Display for Mboxes {
impl<'a> From<&'a imap::types::ZeroCopy<Vec<imap::types::Name>>> for Mboxes<'a> {
fn from(names: &'a imap::types::ZeroCopy<Vec<imap::types::Name>>) -> Self {
Self(names.iter().map(Mbox::from).collect::<Vec<_>>())
}
}
impl fmt::Display for Mboxes<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "\n{}", Table::render(&self.0))
}