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
use std::io;
use console::Term;
pub struct Paging<'a> {
pub pages: usize,
pub current_page: usize,
pub capacity: usize,
pub active: bool,
pub max_capacity: Option<usize>,
term: &'a Term,
current_term_size: (u16, u16),
items_len: usize,
activity_transition: bool,
}
impl<'a> Paging<'a> {
pub fn new(term: &'a Term, items_len: usize, max_capacity: Option<usize>) -> Paging<'a> {
let term_size = term.size();
let capacity = max_capacity
.unwrap_or(std::usize::MAX)
.min(term_size.0 as usize)
.max(3)
- 2;
let pages = (items_len as f64 / capacity as f64).ceil() as usize;
Paging {
pages,
current_page: 0,
capacity,
active: pages > 1,
term,
current_term_size: term_size,
items_len,
max_capacity,
activity_transition: true,
}
}
pub fn update(&mut self, cursor_pos: usize) -> io::Result<()> {
let new_term_size = self.term.size();
if self.current_term_size != new_term_size {
self.current_term_size = new_term_size;
self.capacity = self
.max_capacity
.unwrap_or(std::usize::MAX)
.min(self.current_term_size.0 as usize)
.max(3)
- 2;
self.pages = (self.items_len as f64 / self.capacity as f64).ceil() as usize;
}
if self.active == (self.pages > 1) {
self.activity_transition = false;
} else {
self.active = self.pages > 1;
self.activity_transition = true;
self.term.clear_last_lines(self.capacity)?;
}
if cursor_pos != !0
&& (cursor_pos < self.current_page * self.capacity
|| cursor_pos >= (self.current_page + 1) * self.capacity)
{
self.current_page = cursor_pos / self.capacity;
}
Ok(())
}
pub fn render_prompt<F>(&mut self, mut render_prompt: F) -> io::Result<()>
where
F: FnMut(Option<(usize, usize)>) -> io::Result<()>,
{
if self.active {
let paging_info = Some((self.current_page + 1, self.pages));
render_prompt(paging_info)?;
} else if self.activity_transition {
render_prompt(None)?;
}
self.term.flush()?;
Ok(())
}
pub fn next_page(&mut self) -> usize {
if self.current_page == self.pages - 1 {
self.current_page = 0;
} else {
self.current_page += 1;
}
self.current_page * self.capacity
}
pub fn previous_page(&mut self) -> usize {
if self.current_page == 0 {
self.current_page = self.pages - 1;
} else {
self.current_page -= 1;
}
self.current_page * self.capacity
}
}