1 use chrono::Duration; 2 use clap::ArgMatches; 3 use ffsend_api::config::SEND_DEFAULT_EXPIRE_TIME; 4 use prettytable::{format::FormatBuilder, Cell, Row, Table}; 5 6 use crate::client::to_duration; 7 use crate::cmd::matcher::{debug::DebugMatcher, main::MainMatcher, Matcher}; 8 use crate::error::ActionError; 9 #[cfg(feature = "clipboard-bin")] 10 use crate::util::ClipboardType; 11 use crate::util::{api_version_list, features_list, format_bool, format_duration}; 12 13 /// A file debug action. 14 pub struct Debug<'a> { 15 cmd_matches: &'a ArgMatches<'a>, 16 } 17 18 impl<'a> Debug<'a> { 19 /// Construct a new debug action. new(cmd_matches: &'a ArgMatches<'a>) -> Self20 pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self { 21 Self { cmd_matches } 22 } 23 24 /// Invoke the debug action. 25 // TODO: create a trait for this method invoke(&self) -> Result<(), ActionError>26 pub fn invoke(&self) -> Result<(), ActionError> { 27 // Create the command matchers 28 let matcher_main = MainMatcher::with(self.cmd_matches).unwrap(); 29 let matcher_debug = DebugMatcher::with(self.cmd_matches).unwrap(); 30 31 // Create a table for all debug information 32 let mut table = Table::new(); 33 table.set_format(FormatBuilder::new().padding(0, 2).build()); 34 35 // The crate version 36 table.add_row(Row::new(vec![ 37 Cell::new("Version:"), 38 Cell::new(crate_version!()), 39 ])); 40 41 // The default host 42 table.add_row(Row::new(vec![ 43 Cell::new("Host:"), 44 Cell::new(matcher_debug.host().as_str()), 45 ])); 46 47 // The history file 48 #[cfg(feature = "history")] 49 table.add_row(Row::new(vec![ 50 Cell::new("History file:"), 51 Cell::new(matcher_main.history().to_str().unwrap_or("?")), 52 ])); 53 54 // The timeouts 55 table.add_row(Row::new(vec![ 56 Cell::new("Timeout:"), 57 Cell::new( 58 &to_duration(matcher_main.timeout()) 59 .map(|t| { 60 format_duration( 61 Duration::from_std(t).expect("failed to convert timeout duration"), 62 ) 63 }) 64 .unwrap_or("disabled".into()), 65 ), 66 ])); 67 table.add_row(Row::new(vec![ 68 Cell::new("Transfer timeout:"), 69 Cell::new( 70 &to_duration(matcher_main.transfer_timeout()) 71 .map(|t| { 72 format_duration( 73 Duration::from_std(t) 74 .expect("failed to convert transfer timeout duration"), 75 ) 76 }) 77 .unwrap_or("disabled".into()), 78 ), 79 ])); 80 81 // The default host 82 table.add_row(Row::new(vec![ 83 Cell::new("Default expiry:"), 84 Cell::new(&format_duration(Duration::seconds( 85 SEND_DEFAULT_EXPIRE_TIME as i64, 86 ))), 87 ])); 88 89 // Render a list of compiled features 90 table.add_row(Row::new(vec![ 91 Cell::new("Features:"), 92 Cell::new(&features_list().join(", ")), 93 ])); 94 95 // Render a list of compiled features 96 table.add_row(Row::new(vec![ 97 Cell::new("API support:"), 98 Cell::new(&api_version_list().join(", ")), 99 ])); 100 101 // Show used crypto backend 102 table.add_row(Row::new(vec![ 103 Cell::new("Crypto backend:"), 104 #[cfg(feature = "crypto-ring")] 105 Cell::new("ring"), 106 #[cfg(feature = "crypto-openssl")] 107 Cell::new("OpenSSL"), 108 ])); 109 110 // Clipboard information 111 #[cfg(feature = "clipboard-bin")] 112 table.add_row(Row::new(vec![ 113 Cell::new("Clipboard:"), 114 Cell::new(&format!("{}", ClipboardType::select())), 115 ])); 116 117 // Show whether quiet is used 118 table.add_row(Row::new(vec![ 119 Cell::new("Quiet:"), 120 Cell::new(format_bool(matcher_main.quiet())), 121 ])); 122 123 // Show whether verbose is used 124 table.add_row(Row::new(vec![ 125 Cell::new("Verbose:"), 126 Cell::new(format_bool(matcher_main.verbose())), 127 ])); 128 129 // Print the debug table 130 table.printstd(); 131 132 Ok(()) 133 } 134 } 135