summaryrefslogtreecommitdiff
path: root/src/arguments.rs
blob: bd0fdcb2a4f7f69e46a3d42d7c3640b789edf2e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::path::PathBuf;

use clap::{value_parser, Parser, Subcommand};

use crate::error::Error;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SortKey {
    Date,
    Sender,
    Subject,
    Size,
}

#[derive(PartialEq, Eq, Clone)]
pub enum SortOrder {
    Ascending,
    Descending,
}

#[derive(PartialEq, Eq, Clone)]
pub struct SortInfo {
    pub key: SortKey,
    pub order: SortOrder,
}

impl std::str::FromStr for SortInfo {
    type Err = Error;

    fn from_str(mut value: &str) -> Result<Self, Self::Err> {
        if value == "" {
            return Ok(SortInfo {
                key: SortKey::Date,
                order: SortOrder::Ascending,
            });
        }
        let order = if value.starts_with('!') {
            value = &value[1..];
            SortOrder::Descending
        } else {
            SortOrder::Ascending
        };
        let key = match value.to_ascii_lowercase().as_str() {
            "date" => SortKey::Date,
            "sender" => SortKey::Sender,
            "subject" => SortKey::Subject,
            "size" => SortKey::Size,
            v => return Err(Error::SortOrder(format!("invalid sort order {:}", v))),
        };
        Ok(SortInfo { key, order })
    }
}

impl std::fmt::Debug for SortInfo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(
            f,
            "{}{:?}",
            match self.order {
                SortOrder::Descending => "!",
                SortOrder::Ascending => "",
            },
            self.key
        )
    }
}

#[derive(Subcommand)]
pub enum Mode {
    List {
        subfolder: String,
        start: usize,
        end: usize,
        #[arg(value_parser = value_parser!(SortInfo))]
        sortby: SortInfo,
    },
    Search {
        pattern: String,
        subfolder: String,
    },
    Count {
        subfolder: String,
    },
    Read {
        subfolder: String,
        mid: String,
    },
    Raw {
        subfolder: String,
        mid: String,
        mime_path: String,
    },
    Folders,
    Move {
        mid: String,
        from: String,
        to: String,
    },
    Remove {
        subfolder: String,
        mid: String,
    },
}

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
pub struct Arguments {
    pub maildir_path: PathBuf,
    pub sys_user: String,
    pub mail_user: String,
    #[command(subcommand)]
    pub mode: Mode,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn sort_info() {
        assert_eq!(
            "!date".parse::<SortInfo>().unwrap(),
            SortInfo {
                key: SortKey::Date,
                order: SortOrder::Descending
            }
        );
    }
}