From 34ab0f4fa5d178e52df8f761e9ec77fcf93c4d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Fri, 25 Feb 2022 21:21:48 +0100 Subject: [PATCH] fix sort command not found (#308) --- CHANGELOG.md | 2 + src/backends/backend.rs | 8 ++- src/backends/imap/imap_backend.rs | 72 ++++++++++++++++++++----- src/backends/maildir/maildir_backend.rs | 22 +++++--- src/backends/notmuch/notmuch_backend.rs | 26 ++++++--- src/msg/msg_handler.rs | 6 +-- 6 files changed, 105 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3880cb3..8acd964 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Build failure due to `imap` version [#303] - No tilde expansion in `maildir-dir` [#305] +- Unknown command SORT [#308] ## [0.5.6] - 2022-02-22 @@ -440,3 +441,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#289]: https://github.com/soywod/himalaya/issues/289 [#303]: https://github.com/soywod/himalaya/issues/303 [#305]: https://github.com/soywod/himalaya/issues/305 +[#308]: https://github.com/soywod/himalaya/issues/308 diff --git a/src/backends/backend.rs b/src/backends/backend.rs index 8162822..b7194f6 100644 --- a/src/backends/backend.rs +++ b/src/backends/backend.rs @@ -21,8 +21,14 @@ pub trait Backend<'a> { fn get_envelopes( &mut self, mbox: &str, + page_size: usize, + page: usize, + ) -> Result>; + fn find_envelopes( + &mut self, + mbox: &str, + query: &str, sort: &str, - filter: &str, page_size: usize, page: usize, ) -> Result>; diff --git a/src/backends/imap/imap_backend.rs b/src/backends/imap/imap_backend.rs index 8ed0b3b..5d328bf 100644 --- a/src/backends/imap/imap_backend.rs +++ b/src/backends/imap/imap_backend.rs @@ -229,8 +229,42 @@ impl<'a> Backend<'a> for ImapBackend<'a> { fn get_envelopes( &mut self, mbox: &str, + page_size: usize, + page: usize, + ) -> Result> { + let last_seq = self + .sess()? + .select(mbox) + .context(format!("cannot select mailbox {:?}", mbox))? + .exists as usize; + debug!("last sequence number: {:?}", last_seq); + if last_seq == 0 { + return Ok(Box::new(ImapEnvelopes::default())); + } + + let range = if page_size > 0 { + let cursor = page * page_size; + let begin = 1.max(last_seq - cursor); + let end = begin - begin.min(page_size) + 1; + format!("{}:{}", end, begin) + } else { + String::from("1:*") + }; + debug!("range: {:?}", range); + + let fetches = self + .sess()? + .fetch(&range, "(ENVELOPE FLAGS INTERNALDATE)") + .context(format!("cannot fetch messages within range {:?}", range))?; + let envelopes: ImapEnvelopes = fetches.try_into()?; + Ok(Box::new(envelopes)) + } + + fn find_envelopes( + &mut self, + mbox: &str, + query: &str, sort: &str, - filter: &str, page_size: usize, page: usize, ) -> Result> { @@ -239,24 +273,36 @@ impl<'a> Backend<'a> for ImapBackend<'a> { .select(mbox) .context(format!("cannot select mailbox {:?}", mbox))? .exists; + debug!("last sequence number: {:?}", last_seq); if last_seq == 0 { return Ok(Box::new(ImapEnvelopes::default())); } - let sort: SortCriteria = sort.try_into()?; - let charset = imap::extensions::sort::SortCharset::Utf8; let begin = page * page_size; let end = begin + (page_size - 1); - let seqs: Vec = self - .sess()? - .sort(&sort, charset, filter) - .context(format!( - "cannot search in {:?} with query {:?}", - mbox, filter - ))? - .iter() - .map(|seq| seq.to_string()) - .collect(); + let seqs: Vec = if sort.is_empty() { + self.sess()? + .search(query) + .context(format!( + "cannot find envelopes in {:?} with query {:?}", + mbox, query + ))? + .iter() + .map(|seq| seq.to_string()) + .collect() + } else { + let sort: SortCriteria = sort.try_into()?; + let charset = imap::extensions::sort::SortCharset::Utf8; + self.sess()? + .sort(&sort, charset, query) + .context(format!( + "cannot find envelopes in {:?} with query {:?}", + mbox, query + ))? + .iter() + .map(|seq| seq.to_string()) + .collect() + }; if seqs.is_empty() { return Ok(Box::new(ImapEnvelopes::default())); } diff --git a/src/backends/maildir/maildir_backend.rs b/src/backends/maildir/maildir_backend.rs index 0fd184c..44618f2 100644 --- a/src/backends/maildir/maildir_backend.rs +++ b/src/backends/maildir/maildir_backend.rs @@ -69,17 +69,12 @@ impl<'a> Backend<'a> for MaildirBackend<'a> { fn get_envelopes( &mut self, mdir: &str, - _sort: &str, - filter: &str, page_size: usize, page: usize, ) -> Result> { let mdir = self.get_mdir_from_name(mdir)?; - let mail_entries = match filter { - "new" => mdir.list_new(), - _ => mdir.list_cur(), - }; - let mut envelopes: MaildirEnvelopes = mail_entries + let mut envelopes: MaildirEnvelopes = mdir + .list_cur() .try_into() .context("cannot parse maildir envelopes from {:?}")?; envelopes.sort_by(|a, b| b.date.partial_cmp(&a.date).unwrap()); @@ -96,6 +91,19 @@ impl<'a> Backend<'a> for MaildirBackend<'a> { Ok(Box::new(envelopes)) } + fn find_envelopes( + &mut self, + _mdir: &str, + _query: &str, + _sort: &str, + _page_size: usize, + _page: usize, + ) -> Result> { + Err(anyhow!( + "cannot find maildir envelopes: feature not implemented" + )) + } + fn add_msg(&mut self, mdir: &str, msg: &[u8], flags: &str) -> Result> { let mdir = self.get_mdir_from_name(mdir)?; let flags: MaildirFlags = flags.try_into()?; diff --git a/src/backends/notmuch/notmuch_backend.rs b/src/backends/notmuch/notmuch_backend.rs index 30ed63e..99ff475 100644 --- a/src/backends/notmuch/notmuch_backend.rs +++ b/src/backends/notmuch/notmuch_backend.rs @@ -51,18 +51,30 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> { fn get_envelopes( &mut self, mdir: &str, - _sort: &str, - filter: &str, page_size: usize, page: usize, ) -> Result> { - let query = self + unimplemented!(); + } + + fn find_envelopes( + &mut self, + _mdir: &str, + query: &str, + _sort: &str, + _page_size: usize, + _page: usize, + ) -> Result> { + let query_builder = self .db - .create_query(filter) - .context("cannot create query")?; - let msgs: NotmuchEnvelopes = query + .create_query(query) + .context("cannot create notmuch query")?; + let msgs: NotmuchEnvelopes = query_builder .search_messages() - .context("cannot get messages")? + .context(format!( + "cannot find notmuch envelopes with query {:?}", + query + ))? .try_into()?; Ok(Box::new(msgs)) } diff --git a/src/msg/msg_handler.rs b/src/msg/msg_handler.rs index 3bd5dd3..7cd093d 100644 --- a/src/msg/msg_handler.rs +++ b/src/msg/msg_handler.rs @@ -108,7 +108,7 @@ pub fn list<'a, P: PrinterService, B: Backend<'a> + ?Sized>( ) -> Result<()> { let page_size = page_size.unwrap_or(config.default_page_size); debug!("page size: {}", page_size); - let msgs = imap.get_envelopes(mbox, "arrival:desc", "all", page_size, page)?; + let msgs = imap.get_envelopes(mbox, page_size, page)?; trace!("envelopes: {:?}", msgs); printer.print_table(msgs, PrintTableOpts { max_width }) } @@ -273,7 +273,7 @@ pub fn search<'a, P: PrinterService, B: Backend<'a> + ?Sized>( ) -> Result<()> { let page_size = page_size.unwrap_or(config.default_page_size); debug!("page size: {}", page_size); - let msgs = backend.get_envelopes(mbox, "arrival:desc", &query, page_size, page)?; + let msgs = backend.find_envelopes(mbox, &query, "", page_size, page)?; trace!("messages: {:#?}", msgs); printer.print_table(msgs, PrintTableOpts { max_width }) } @@ -292,7 +292,7 @@ pub fn sort<'a, P: PrinterService, B: Backend<'a> + ?Sized>( ) -> Result<()> { let page_size = page_size.unwrap_or(config.default_page_size); debug!("page size: {}", page_size); - let msgs = backend.get_envelopes(mbox, &sort, &query, page_size, page)?; + let msgs = backend.find_envelopes(mbox, &query, &sort, page_size, page)?; trace!("envelopes: {:#?}", msgs); printer.print_table(msgs, PrintTableOpts { max_width }) }