1use crate::regex;
2use std::collections::VecDeque;
3use std::process::{Child, Command, Stdio};
4
5pub struct Pager {
6 command: String,
7 args: VecDeque<String>,
8 failed: bool,
9}
10
11impl Pager {
12 pub fn new(pager: String) -> Self {
13 let regex = regex!(r"\bless\b");
14 let mut args = pager.split_whitespace().map(String::from).collect::<VecDeque<_>>();
15 let command = args.pop_front().unwrap_or_else(|| String::from("less"));
16 if regex.is_match(&command) {
17 args.push_back(String::from("-FRX"));
38 }
39 Self { command, args, failed: false }
40 }
41
42 pub fn spawn_child(&mut self) -> Option<Child> {
43 if !self.failed {
44 let child = spawn_child(&self.command, &self.args);
45 self.failed = child.is_none();
46 child
47 } else {
48 None
49 }
50 }
51}
52
53fn spawn_child(command: &str, args: &VecDeque<String>) -> Option<Child> {
54 Command::new(command).args(args).stdin(Stdio::piped()).spawn().ok()
55}
56
57#[cfg(test)]
58mod tests {
59 use crate::core::pager::Pager;
60 use pretty_assertions::assert_eq;
61
62 #[test]
63 fn test_empty_command_is_set_to_less() {
64 let pager = Pager::new(String::from(" "));
65 assert_eq!(pager.command, "less");
66 assert_eq!(pager.args, vec!["-FRX"]);
67 }
68
69 #[test]
70 fn test_options_are_extended_for_less() {
71 let pager = Pager::new(String::from(" less "));
72 assert_eq!(pager.command, "less");
73 assert_eq!(pager.args, vec!["-FRX"]);
74
75 let pager = Pager::new(String::from(" less -abc -def "));
76 assert_eq!(pager.command, "less");
77 assert_eq!(pager.args, vec!["-abc", "-def", "-FRX"]);
78 }
79
80 #[test]
81 fn test_options_not_extended_for_more() {
82 let pager = Pager::new(String::from(" more "));
83 assert_eq!(pager.command, "more");
84 assert_eq!(pager.args, Vec::<String>::new());
85
86 let pager = Pager::new(String::from(" more -abc -def "));
87 assert_eq!(pager.command, "more");
88 assert_eq!(pager.args, vec!["-abc", "-def"]);
89 }
90}