浏览代码

accounts: suggest tips on mailbox_by_path error

If Account::mailbox_by_path() fails, suggest matching mailbox paths
using aho_corasick case insensitive matching, and also suggest to the
user to inspect mailboxes with the manage-mailboxes command.

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
Manos Pitsidianakis 7 月之前
父节点
当前提交
a389772d
共有 3 个文件被更改,包括 49 次插入1 次删除
  1. 1 0
      Cargo.lock
  2. 1 0
      meli/Cargo.toml
  3. 47 1
      meli/src/accounts.rs

+ 1 - 0
Cargo.lock

@@ -1266,6 +1266,7 @@ dependencies = [
 name = "meli"
 version = "0.8.8"
 dependencies = [
+ "aho-corasick",
  "assert_cmd",
  "async-task",
  "bitflags 2.6.0",

+ 1 - 0
meli/Cargo.toml

@@ -23,6 +23,7 @@ name = "meli"
 path = "src/lib.rs"
 
 [dependencies]
+aho-corasick = { version = "1.1.3" }
 async-task = { version = "^4.2.0" }
 bitflags = { version = "2.4", features = ["serde"] }
 crossbeam = { version = "^0.8" }

+ 47 - 1
meli/src/accounts.rs

@@ -1331,7 +1331,53 @@ impl Account {
         {
             Ok(*mailbox_hash)
         } else {
-            Err(Error::new("Mailbox with that path not found."))
+            use aho_corasick::AhoCorasick;
+
+            let nodes = self
+                .list_mailboxes()
+                .into_iter()
+                .map(|n| (n.hash, n.depth))
+                .collect::<BTreeMap<MailboxHash, usize>>();
+            let mut entries = self
+                .mailbox_entries
+                .iter()
+                .map(|(h, f)| (h, f.ref_mailbox.path()))
+                .collect::<Vec<_>>();
+            entries.sort_by_cached_key(|(h, _)| nodes.get(h).cloned().unwrap_or(usize::MAX));
+            let patterns = &[path.trim_matches('/')];
+            let mut potential_matches = IndexSet::new();
+            for (_, haystack) in entries {
+                let ac = AhoCorasick::builder()
+                    .ascii_case_insensitive(true)
+                    .build(patterns)
+                    .unwrap();
+                if ac.find_iter(haystack).next().is_some() {
+                    potential_matches.insert(haystack.to_string());
+                }
+            }
+            const MANAGE_MAILBOXES_TIP: &str = "You can inspect the list of mailbox paths of an \
+                                                account with the manage-mailboxes command.";
+            let details_msg = if potential_matches.is_empty() {
+                Cow::Borrowed(MANAGE_MAILBOXES_TIP)
+            } else {
+                let mut potential_matches = potential_matches.into_iter().collect::<Vec<_>>();
+                let matches_length = potential_matches.len();
+                potential_matches.truncate(5);
+                Cow::Owned(format!(
+                    "Some matching paths that were found: {matches:?}{others}. {tip}",
+                    matches = potential_matches,
+                    tip = MANAGE_MAILBOXES_TIP,
+                    others = if matches_length > 5 {
+                        format!(" and {} others", matches_length - 5)
+                    } else {
+                        String::with_capacity(0)
+                    }
+                ))
+            };
+
+            Err(Error::new("Mailbox with that path not found.")
+                .set_details(details_msg)
+                .set_kind(ErrorKind::NotFound))
         }
     }