summaryrefslogtreecommitdiffstats
path: root/src/options/help.rs
blob: d7b986a2d9f04dedb6cef11428bd255e2ff0f36e (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
130
131
132
133
134
135
use std::fmt;

use crate::fs::feature::xattr;
use crate::options::flags;
use crate::options::parser::MatchedFlags;


static USAGE: &str = r##"Usage:
  exa [options] [files...]

META OPTIONS
  -?, --help         show list of command-line options
  -v, --version      show version of exa

DISPLAY OPTIONS
  -1, --oneline      display one entry per line
  -l, --long         display extended file metadata as a table
  -G, --grid         display entries as a grid (default)
  -x, --across       sort the grid across, rather than downwards
  -R, --recurse      recurse into directories
  -T, --tree         recurse into directories as a tree
  -F, --classify     display type indicator by file names
  --colo[u]r=WHEN    when to use terminal colours (always, auto, never)
  --colo[u]r-scale   highlight levels of file sizes distinctly
  --icons            display icons

FILTERING AND SORTING OPTIONS
  -a, --all                  show hidden and 'dot' files
  -d, --list-dirs            list directories like regular files
  -L, --level DEPTH          limit the depth of recursion
  -r, --reverse              reverse the sort order
  -s, --sort SORT_FIELD      which field to sort by
  --group-directories-first  list directories before other files
  -D, --only-dirs            list only directories
  -I, --ignore-glob GLOBS    glob patterns (pipe-separated) of files to ignore
  --git-ignore               ignore files mentioned in '.gitignore'
  Valid sort fields:         name, Name, extension, Extension, size, type,
                             modified, accessed, created, inode, and none.
                             date, time, old, and new all refer to modified.

LONG VIEW OPTIONS
  -b, --binary         list file sizes with binary prefixes
  -B, --bytes          list file sizes in bytes, without any prefixes
  -g, --group          list each file's group
  -h, --header         add a header row to each column
  -H, --links          list each file's number of hard links
  -i, --inode          list each file's inode number
  -m, --modified       use the modified timestamp field
  -S, --blocks         show number of file system blocks
  -t, --time FIELD     which timestamp field to list (modified, accessed, created)
  -u, --accessed       use the accessed timestamp field
  -U, --created        use the created timestamp field
  --changed            use the changed timestamp field
  --time-style         how to format timestamps (default, iso, long-iso, full-iso)
  --no-permissions     suppress the permissions field
  --octal-permissions  list each file's permission in octal format
  --no-filesize        suppress the filesize field
  --no-user            suppress the user field
  --no-time            suppress the time field"##;

static GIT_HELP:      &str = r##"  --git                list each file's Git status, if tracked or ignored"##;
static EXTENDED_HELP: &str = r##"  -@, --extended       list each file's extended attributes and sizes"##;


/// All the information needed to display the help text, which depends
/// on which features are enabled and whether the user only wants to
/// see one section’s help.
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct HelpString;

impl HelpString {

    /// Determines how to show help, if at all, based on the user’s
    /// command-line arguments. This one works backwards from the other
    /// ‘deduce’ functions, returning Err if help needs to be shown.
    ///
    /// We don’t do any strict-mode error checking here: it’s OK to give
    /// the --help or --long flags more than once. Actually checking for
    /// errors when the user wants help is kind of petty!
    pub fn deduce(matches: &MatchedFlags<'_>) -> Option<Self> {
        if matches.count(&flags::HELP) > 0 {
            Some(Self)
        }
        else {
            None
        }
    }
}

impl fmt::Display for HelpString {

    /// Format this help options into an actual string of help
    /// text to be displayed to the user.
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        writeln!(f, "{}", USAGE)?;

        if cfg!(feature="git") {
            writeln!(f, "{}", GIT_HELP)?;
        }

        if xattr::ENABLED {
            writeln!(f, "{}", EXTENDED_HELP)?;
        }

        Ok(())
    }
}


#[cfg(test)]
mod test {
    use crate::options::{Options, OptionsResult};
    use std::ffi::OsStr;

    #[test]
    fn help() {
        let args = vec![ OsStr::new("--help") ];
        let opts = Options::parse(args, &None);
        assert!(matches!(opts, OptionsResult::Help(_)));
    }

    #[test]
    fn help_with_file() {
        let args = vec![ OsStr::new("--help"), OsStr::new("me") ];
        let opts = Options::parse(args, &None);
        assert!(matches!(opts, OptionsResult::Help(_)));
    }

    #[test]
    fn unhelpful() {
        let args = vec![];
        let opts = Options::parse(args, &None);
        assert!(! matches!(opts, OptionsResult::Help(_)))  // no help when --help isn’t passed
    }
}