diff --git a/Cargo.lock b/Cargo.lock index 2bc3c03..2f53987 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -202,10 +202,33 @@ dependencies = [ "bitflags 1.3.2", "strsim", "textwrap", - "unicode-width", + "unicode-width 0.1.11", "vec_map", ] +[[package]] +name = "cli-table" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14da8d951cef7cc4f13ccc9b744d736963d57863c7e6fc33c070ea274546082c" +dependencies = [ + "cli-table-derive", + "csv", + "termcolor", + "unicode-width 0.2.1", +] + +[[package]] +name = "cli-table-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c1b60bae2c3d45228dfb096046aa51ef6c300de70b658d7a13fcb0c4f832e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "colored" version = "2.1.0" @@ -252,9 +275,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -286,16 +309,6 @@ dependencies = [ "dirs-sys", ] -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - [[package]] name = "dirs-sys" version = "0.4.1" @@ -308,29 +321,12 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - [[package]] name = "encoding_rs" version = "0.8.33" @@ -934,7 +930,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.106", ] [[package]] @@ -985,20 +981,6 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" -[[package]] -name = "prettytable-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" -dependencies = [ - "csv", - "encode_unicode", - "is-terminal", - "lazy_static", - "term", - "unicode-width", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1025,9 +1007,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.74" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -1043,9 +1025,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -1189,6 +1171,7 @@ dependencies = [ "alpm", "anyhow", "chrono", + "cli-table", "colored", "directories", "env_logger", @@ -1201,13 +1184,13 @@ dependencies = [ "libflate", "libscmp", "log", - "prettytable-rs", "raur", "regex", "rm_rf", "ruzstd", "srcinfo", "structopt", + "supports-hyperlinks", "tar", "termize", "uname", @@ -1264,12 +1247,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - [[package]] name = "ruzstd" version = "0.4.0" @@ -1346,7 +1323,7 @@ checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.106", ] [[package]] @@ -1452,6 +1429,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "supports-hyperlinks" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d" +dependencies = [ + "is-terminal", +] + [[package]] name = "syn" version = "1.0.109" @@ -1465,9 +1451,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.46" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -1518,22 +1504,11 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -1554,7 +1529,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width", + "unicode-width 0.1.11", ] [[package]] @@ -1583,7 +1558,7 @@ checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.106", ] [[package]] @@ -1594,7 +1569,7 @@ checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.106", ] [[package]] @@ -1745,6 +1720,12 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" + [[package]] name = "untrusted" version = "0.9.0" @@ -1816,7 +1797,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.106", "wasm-bindgen-shared", ] @@ -1850,7 +1831,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2085,5 +2066,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.106", ] diff --git a/Cargo.toml b/Cargo.toml index 70d64d2..7d5c9de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ libscmp = "0.2.0" alpm = { version = "2.2.3", default-features = false, features = [], optional = true } anyhow = { version = "1.0.79", default-features = false, features = ["std", "backtrace"] } chrono = { version = "0.4.31", default-features = false, features = ["std", "clock"] } +cli-table = "0.5.0" colored = "2.0.2" directories = "5.0.1" env_logger = "0.10.1" @@ -39,13 +40,13 @@ lazy_static = "1.4.0" libc = { version = "0.2.151", default-features = false } libflate = "2.0.0" log = { version = "0.4.20", default-features = false } -prettytable-rs = "0.10.0" raur = { version = "7.0.0", default-features = false, features = ["blocking", "rustls-tls"] } regex = { version = "1.9.6", default-features = false, features = ["perf"] } rm_rf = "0.6.2" ruzstd = "0.4.0" srcinfo = "1.1.0" structopt = "0.3.26" +supports-hyperlinks = "2.1.0" tar = { version = "0.4.40", default-features = false } termize = "0.1.1" uname = "0.1.1" diff --git a/src/action_upgrade.rs b/src/action_upgrade.rs index 48b3161..1f70c23 100644 --- a/src/action_upgrade.rs +++ b/src/action_upgrade.rs @@ -5,14 +5,16 @@ use crate::aur_rpc_utils; use crate::pacman; use crate::rua_paths::RuaPaths; use crate::terminal_util; +use crate::terminal_util::try_hyperlink_package_name; use anyhow::Result; +use cli_table::format::Border; +use cli_table::format::Separator; +use cli_table::Table; use colored::*; use itertools::Itertools; use lazy_static::lazy_static; use log::debug; use log::warn; -use prettytable::format::*; -use prettytable::*; use regex::Regex; use std::cmp::Ordering; use std::collections::HashSet; @@ -145,24 +147,26 @@ fn calculate_upgrade( } fn print_outdated(outdated: &[(String, String, String)], nonexistent: &[(String, String)]) { - let mut table = Table::new(); - table.set_titles(row![ + let mut table = vec![vec![ "Package".underline(), "Current".underline(), - "Latest".underline() - ]); + "Latest".underline(), + ]]; for (pkg, local, remote) in outdated { - table.add_row(row![pkg.yellow(), local, remote.green(),]); + table.push(vec![pkg.yellow(), local.to_owned().into(), remote.green()]); } for (pkg, local) in nonexistent { - table.add_row(row![ - pkg.yellow(), - local, + table.push(vec![ + try_hyperlink_package_name(pkg.to_owned(), pkg).yellow(), + local.to_owned().into(), "not found in neither pacman nor AUR, ignoring".dimmed(), ]); } - let fmt: TableFormat = FormatBuilder::new().padding(0, 1).build(); - table.set_format(fmt); - table.printstd(); + + let table = table + .table() + .border(Border::builder().build()) + .separator(Separator::builder().build()); + cli_table::print_stdout(table).unwrap(); } diff --git a/src/print_package_table.rs b/src/print_package_table.rs index fb76eeb..32d8655 100644 --- a/src/print_package_table.rs +++ b/src/print_package_table.rs @@ -1,8 +1,12 @@ +use cli_table::{ + format::{Border, Separator}, + Table, +}; use colored::*; -use prettytable::format::*; -use prettytable::*; use raur::Package; +use crate::terminal_util::try_hyperlink_package_name; + pub fn trunc(s: &str, max_chars: usize) -> String { match s.char_indices().nth(max_chars.max(2)) { None => s.to_owned(), @@ -15,24 +19,27 @@ pub fn trunc(s: &str, max_chars: usize) -> String { pub fn print_package_table(mut packages: Vec, keywords: &[String]) { packages.sort_by(|a, b| b.popularity.partial_cmp(&a.popularity).unwrap()); - let mut table = Table::new(); - table.set_titles(row![ + let mut table = vec![vec![ "Name".underline(), "Version".underline(), - "Description".underline() - ]); + "Description".underline(), + ]]; for package in packages { - let name = highlight(package.name, keywords).yellow(); + let name = highlight(package.name.clone(), keywords); + let name = try_hyperlink_package_name(name, &package.name); + let name = name.yellow(); let version = highlight(trunc(&package.version, 14), keywords).green(); let description = package.description.unwrap_or_else(|| String::from("")); let description = highlight(description, keywords); - table.add_row(row![name, version, description]); + table.push(vec![name, version, description.into()]); } - let fmt = FormatBuilder::new().padding(0, 1).build(); - table.set_format(fmt); - table.printstd(); + let table = table + .table() + .border(Border::builder().build()) + .separator(Separator::builder().build()); + cli_table::print_stdout(table).unwrap(); } fn highlight(mut text: String, keywords: &[String]) -> String { diff --git a/src/terminal_util.rs b/src/terminal_util.rs index ec4663f..1f6740f 100644 --- a/src/terminal_util.rs +++ b/src/terminal_util.rs @@ -50,3 +50,17 @@ pub fn escape_bash_arg(str: &str) -> String { let result = str.replace('\'', "'\\''"); // end quoting, append the literal, start quoting format!("'{}'", result) } + +/// For terminals that support OSC 8 hyperlinks (like iTerm2, Windows Terminal, etc), +/// this will turn the given text into a clickable hyperlink to the given URL. +/// If the terminal does not support hyperlinks, the text is returned unchanged. +/// +/// The text could be of any content, the url is constructed from `package_name`, not `text`. +pub fn try_hyperlink_package_name(mut text: String, package_name: &str) -> String { + if !supports_hyperlinks::supports_hyperlinks() { + return text; + } + let url = format_args!("https://aur.archlinux.org/packages/{}", package_name); + text = format!("\x1B]8;;{}\x1B\\{}\x1B]8;;\x1B\\", url, text); + text +}