1use console::Term;
2
3use crate::Result;
4
5pub struct Paging<'a> {
10 pub pages: usize,
11 pub current_page: usize,
12 pub capacity: usize,
13 pub active: bool,
14 pub max_capacity: Option<usize>,
15 term: &'a Term,
16 current_term_size: (u16, u16),
17 items_len: usize,
18 activity_transition: bool,
19}
20
21impl<'a> Paging<'a> {
22 pub fn new(term: &'a Term, items_len: usize, max_capacity: Option<usize>) -> Paging<'a> {
23 let term_size = term.size();
24 let capacity = max_capacity
26 .unwrap_or(std::usize::MAX)
27 .clamp(3, term_size.0 as usize)
28 - 2;
29 let pages = (items_len as f64 / capacity as f64).ceil() as usize;
30
31 Paging {
32 pages,
33 current_page: 0,
34 capacity,
35 active: pages > 1,
36 term,
37 current_term_size: term_size,
38 items_len,
39 max_capacity,
40 activity_transition: true,
42 }
43 }
44
45 pub fn update_page(&mut self, cursor_pos: usize) {
46 if cursor_pos != !0
47 && (cursor_pos < self.current_page * self.capacity
48 || cursor_pos >= (self.current_page + 1) * self.capacity)
49 {
50 self.current_page = cursor_pos / self.capacity;
51 }
52 }
53
54 pub fn update(&mut self, cursor_pos: usize) -> Result {
56 let new_term_size = self.term.size();
57
58 if self.current_term_size != new_term_size {
59 self.current_term_size = new_term_size;
60 self.capacity = self
61 .max_capacity
62 .unwrap_or(std::usize::MAX)
63 .clamp(3, self.current_term_size.0 as usize)
64 - 2;
65 self.pages = (self.items_len as f64 / self.capacity as f64).ceil() as usize;
66 }
67
68 if self.active == (self.pages > 1) {
69 self.activity_transition = false;
70 } else {
71 self.active = self.pages > 1;
72 self.activity_transition = true;
73 self.term.clear_last_lines(self.capacity)?;
75 }
76
77 self.update_page(cursor_pos);
78
79 Ok(())
80 }
81
82 pub fn render_prompt<F>(&mut self, mut render_prompt: F) -> Result
86 where
87 F: FnMut(Option<(usize, usize)>) -> Result,
88 {
89 if self.active {
90 let paging_info = Some((self.current_page + 1, self.pages));
91 render_prompt(paging_info)?;
92 } else if self.activity_transition {
93 render_prompt(None)?;
94 }
95
96 self.term.flush()?;
97
98 Ok(())
99 }
100
101 pub fn next_page(&mut self) -> usize {
103 if self.current_page == self.pages - 1 {
104 self.current_page = 0;
105 } else {
106 self.current_page += 1;
107 }
108
109 self.current_page * self.capacity
110 }
111
112 pub fn previous_page(&mut self) -> usize {
114 if self.current_page == 0 {
115 self.current_page = self.pages - 1;
116 } else {
117 self.current_page -= 1;
118 }
119
120 self.current_page * self.capacity
121 }
122}