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 clashctl_interactive::{ProxySort, Sortable};
use either::Either;
use owo_colors::OwoColorize;
use terminal_size::{terminal_size, Height, Width};
use crate::model::{Proxies, Proxy};
use crate::ProxyListOpt;
pub trait RenderList {
fn render_list(&self, opt: &ProxyListOpt);
fn render_plain(&self, opt: &ProxyListOpt);
fn render_tree(&self, opt: &ProxyListOpt);
}
impl RenderList for Proxies {
fn render_list(&self, opt: &ProxyListOpt) {
let (Width(terminal_width), _) = terminal_size().unwrap_or((Width(70), Height(0)));
println!("\n{:-<1$}", "", terminal_width as usize);
println!("{:<18}{:<8}NAME", "TYPE", "DELAY");
println!("{:-<1$}", "", terminal_width as usize);
if opt.plain {
self.render_plain(opt)
} else {
self.render_tree(opt)
}
println!("{:-<1$}", "", terminal_width as usize);
}
fn render_plain(&self, opt: &ProxyListOpt) {
let mut list = self.iter().collect::<Vec<_>>();
let sort_method = ProxySort::new(opt.sort_by, opt.sort_order);
list.sort_with(&sort_method);
let iter = if opt.reverse {
Either::Left(list.into_iter().rev())
} else {
Either::Right(list.into_iter())
}
.filter(|x| {
let proxy_type = &x.1.proxy_type;
if opt.include.is_empty() {
!opt.exclude.contains(proxy_type)
} else {
opt.include.contains(proxy_type)
}
});
for (name, proxy) in iter {
let delay = proxy
.history
.get(0)
.map(|x| match x.delay {
0 => "?".to_owned(),
delay => delay.to_string(),
})
.unwrap_or_else(|| "-".into());
let type_name = proxy.proxy_type.to_string();
println!("{:<18}{:<8}{}", type_name.green(), delay, name)
}
}
fn render_tree(&self, opt: &ProxyListOpt) {
let list = self
.iter()
.filter(|x| {
let proxy_type = x.1.proxy_type;
proxy_type.is_group() && !opt.exclude.contains(&proxy_type)
})
.collect::<Vec<_>>();
let groups = if opt.reverse {
Either::Left(list.iter().rev())
} else {
Either::Right(list.iter())
};
let sort_method = ProxySort::new(opt.sort_by, opt.sort_order);
for (name, group) in groups.into_iter() {
println!("{:<16} - {}\n", group.proxy_type.blue(), name);
let mut members = group
.all
.as_ref()
.expect("Proxy groups should have `all`")
.iter()
.map(|member_name| self.iter().find(|(name, _)| &member_name == name).unwrap())
.collect::<Vec<_>>();
members.sort_with(&sort_method);
for (
name,
Proxy {
proxy_type,
history,
..
},
) in members
{
let delay = history
.get(0)
.map(|x| match x.delay {
0 => "?".to_owned(),
delay => delay.to_string(),
})
.unwrap_or_else(|| "-".into());
println!(" {:<16}{:<8}{}", proxy_type.green(), delay, name)
}
println!();
}
}
}