1use crate::client::StatEntry;
2use opendal::EntryMode;
3use prettytable::{format, row, Table};
4
5fn parse_content_length(input: &str, raw: bool) -> String {
6 if raw || input.is_empty() {
7 return input.to_string();
8 }
9
10 match input.len() {
11 1..=3 => format!("{input}B"),
12 4..=6 => {
13 let mut kilobytes = input.to_string();
14 kilobytes.truncate(input.len() - 2);
15 let mut kilobytes: Vec<char> = kilobytes.chars().collect();
16 kilobytes.insert(kilobytes.len() - 1, '.');
17 let kilobytes: String = kilobytes.into_iter().collect();
18 format!("{}kB", kilobytes)
19 }
20 _ => {
21 let mut megabytes = input.to_string();
22 megabytes.truncate(input.len() - 5);
23 let mut megabytes: Vec<char> = megabytes.chars().collect();
24 megabytes.insert(megabytes.len() - 1, '.');
25 let megabytes: String = megabytes.into_iter().collect();
26 format!("{}MB", megabytes)
27 }
28 }
29}
30
31pub fn log_profiles_table(mut items: Vec<&String>, current: Option<&str>) {
32 let mut table = Table::new();
33
34 table.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
35
36 table.set_titles(row![Fgb->"", Fgb->"name"]);
37 items.sort();
38 for item in items.iter_mut() {
39 let is_current = current.is_some_and(|val| val == item.as_str());
40 if is_current {
41 table.add_row(row![Fgcb->"👉", Fbb->item]);
42 } else {
43 table.add_row(row!["", Fbb->item]);
44 }
45 }
46
47 table.print_tty(true).unwrap();
48}
49
50pub fn log_files_table(items: &[StatEntry], raw: bool, should_paginate: bool) {
51 let mut table = Table::new();
52
53 table.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
54
55 table.set_titles(row!["", Fgb->"name", Fgb->"content-type", Fgb->"size", Fgb->"type"]);
56 for (line, item) in items.iter().enumerate() {
57 let line = line + 1;
58 match item.3 {
59 EntryMode::FILE => {
60 table.add_row(row![Fw-> line, Fw->item.0,Fbb->item.1,Fbb->parse_content_length(&item.2, raw),Fbb->"file"]);
61 }
62 EntryMode::DIR => {
63 table.add_row(row![Fw-> line, Fm->item.0, "", "", Fmb->"dir"]);
64 }
65 EntryMode::Unknown => {}
66 };
67 }
68
69 if !should_paginate {
70 table.add_row(row![Fw -> "", Fm-> "...", "", "", ""]);
71 }
72
73 table.print_tty(true).unwrap();
74}
75
76pub enum NextAction {
77 Quit,
78 Next,
79 Print(usize),
80}
81
82pub async fn what_next() -> NextAction {
83 let mut input = String::new();
84 let _ = std::io::stdin().read_line(&mut input);
85 let trimmed_len = input.len() - 1;
86
87 if let Ok(idx) = &input[..trimmed_len].parse::<usize>() {
88 return NextAction::Print(*idx);
89 }
90
91 match (trimmed_len, &input.as_bytes()[..trimmed_len]) {
92 (1, [b'q']) => NextAction::Quit,
93 _ => NextAction::Next,
94 }
95}
96
97#[macro_export]
98macro_rules! opendal_builder {
99 ($builder:expr, $( $opt:expr => $method:ident ),* ) => {{
100 let builder = $builder;
101 $(
102 let builder = if let Some(value) = $opt {
103 builder.$method(value)
104 } else {
105 builder
106 };
107 )*
108 builder
109 }};
110}