~matthiasbeyer/imag

967063e15505c199b46ec230bd50a6ca4fa1c396 — Matthias Beyer 9 months ago 93d3bda imag-mail/thread-list
Add subcommand for listing a whole mail thread

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
M bin/domain/imag-mail/src/lib.rs => bin/domain/imag-mail/src/lib.rs +2 -0
@@ 76,6 76,7 @@ use libimagstore::iter::get::StoreIdGetIteratorExtension;

mod ui;
mod util;
mod thread;

/// Marker enum for implementing ImagApplication on
///


@@ 90,6 91,7 @@ impl ImagApplication for ImagMail {
            "list"        => list(&rt),
            "unread"      => unread(&rt),
            "mail-store"  => mail_store(&rt),
            "thread"      => thread::thread(&rt),
            other               => {
                debug!("Unknown command");
                if rt.handle_unknown_subcommand("imag-mail", other, rt.cli())?.success() {

A bin/domain/imag-mail/src/thread.rs => bin/domain/imag-mail/src/thread.rs +79 -0
@@ 0,0 1,79 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015-2020 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;

use clap::ArgMatches;
use failure::Fallible as Result;
use failure::err_msg;
use resiter::AndThen;

use libimagstore::iter::get::StoreIdGetIteratorExtension;
use libimagstore::storeid::StoreId;
use libimagrt::runtime::Runtime;
use libimagmail::iter::IntoMailIterator;
use libimagmail::mail::Mail;
use libimagmail::store::MailStore;
use libimagentryref::util::get_ref_config;

pub fn thread(rt: &Runtime) -> Result<()> {
    let scmd = rt.cli().subcommand_matches("thread").unwrap();

    match scmd.subcommand_name().ok_or_else(|| err_msg("No subcommand called"))? {
        "list"        => list(&scmd, rt),
        other         => Err(format_err!("Unknown subcommand {}", other)),
    }
}

fn list(scmd: &ArgMatches, rt: &Runtime) -> Result<()> {
    let scmd        = scmd.subcommand_matches("list").unwrap(); // safe by thread::thread()
    let list_format = crate::util::get_mail_print_format("mail.list_format", rt, &scmd)?;
    let refconfig   = get_ref_config(rt, "imag-mail")?;
    let mut out     = rt.stdout();
    let mut i       = 0;

    scmd.values_of("thread-entry-point")
        .unwrap()
        .map(String::from)
        .map(PathBuf::from)
        .map(StoreId::new)
        .into_get_iter(rt.store())
        .into_mail_iterator()
        .and_then_ok(|mail| {
            mail.get_message_id(&refconfig)?
                .ok_or_else(|| format_err!("Message without ID: {}", mail.get_location()))
        })
        .and_then_ok(|mid| {
            rt.store()
                .thread_root_of(mid.clone(), &refconfig)?
                .ok_or_else(|| format_err!("No mail found for Message-Id {}", mid))
        })
        .and_then_ok(|root| root.get_thread(rt.store()))
        .and_then_ok(|iter| {
            for element in iter {
                element
                    .and_then(|e| crate::util::list_mail(&e, i, &refconfig, &list_format, &mut out).map(|_| e))
                    .and_then(|e| rt.report_touched(e.get_location()))?;
                i += 1;
            }
            Ok(())
        })
        .collect::<Result<Vec<_>>>()
        .map(|_| ())
}

M bin/domain/imag-mail/src/ui.rs => bin/domain/imag-mail/src/ui.rs +18 -0
@@ 114,6 114,24 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
                                .version("0.1"))
                    // TODO: We really should be able to filter here.
                    )

        .subcommand(SubCommand::with_name("thread")
                    .about("Operations on threads of mails")
                    .version("0.1")

                    .subcommand(SubCommand::with_name("list")
                                .about("List a thread")
                                .version("0.1")

                                .arg(Arg::with_name("thread-entry-point")
                                     .index(1)
                                     .takes_value(true)
                                     .required(true) // for now
                                     .multiple(true)
                                     .value_name("ID")
                                     .help("A mail for which its thread should be listed"))
                                )
                    )
}

pub struct PathProvider;