remote_files/
util.rs

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}