diff --git a/Cargo.lock b/Cargo.lock index beea940..3c348c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,7 +16,7 @@ dependencies = [ "color-eyre", "colored", "console", - "crossterm", + "crossterm 0.25.0", "dialoguer", "directories", "futures", @@ -25,12 +25,13 @@ dependencies = [ "lazy-regex", "lazy_static", "libc", + "minus", "native-tls", "pacmanconf", - "parking_lot", + "parking_lot 0.12.1", "regex", "serde", - "textwrap", + "textwrap 0.15.0", "tokio", "toml", "tracing", @@ -236,7 +237,7 @@ dependencies = [ "strsim", "termcolor", "terminal_size", - "textwrap", + "textwrap 0.15.0", ] [[package]] @@ -339,6 +340,42 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "crossterm" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c" +dependencies = [ + "bitflags", + "crossterm_winapi", + "libc", + "mio 0.7.14", + "parking_lot 0.11.2", + "signal-hook", + "signal-hook-mio", + "winapi", +] + [[package]] name = "crossterm" version = "0.25.0" @@ -348,8 +385,8 @@ dependencies = [ "bitflags", "crossterm_winapi", "libc", - "mio", - "parking_lot", + "mio 0.8.4", + "parking_lot 0.12.1", "signal-hook", "signal-hook-mio", "winapi", @@ -866,6 +903,34 @@ dependencies = [ "adler", ] +[[package]] +name = "minus" +version = "5.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcbd621a681aa2f5b0e87ab547159ec695d1122fc24a297e4aac307ac74609f" +dependencies = [ + "crossbeam-channel", + "crossbeam-utils", + "crossterm 0.22.1", + "once_cell", + "regex", + "textwrap 0.13.4", + "thiserror", +] + +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + [[package]] name = "mio" version = "0.8.4" @@ -878,6 +943,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + [[package]] name = "native-tls" version = "0.2.10" @@ -896,6 +970,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1012,6 +1095,17 @@ dependencies = [ "cini", ] +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.5", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -1019,7 +1113,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.3", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", ] [[package]] @@ -1326,7 +1434,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" dependencies = [ "libc", - "mio", + "mio 0.7.14", + "mio 0.8.4", "signal-hook", ] @@ -1420,6 +1529,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "textwrap" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd05616119e612a8041ef58f2b578906cc2531a6069047ae092cfb86a325d835" +dependencies = [ + "unicode-width", +] + [[package]] name = "textwrap" version = "0.15.0" @@ -1508,7 +1626,7 @@ dependencies = [ "bytes", "libc", "memchr", - "mio", + "mio 0.8.4", "num_cpus", "once_cell", "pin-project-lite", diff --git a/Cargo.toml b/Cargo.toml index e981cb9..ccb105a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ codegen-units = 1 opt-level = 0 [dependencies] +minus = { version = "5.0.5", features = ["search", "static_output"] } alpm = "2.2.1" alpm-utils = "2.0.0" pacmanconf = "2.0.0" diff --git a/src/interact/mod.rs b/src/interact/mod.rs index 3ebcf7a..efcac85 100644 --- a/src/interact/mod.rs +++ b/src/interact/mod.rs @@ -1,10 +1,12 @@ pub mod macros; mod multi_select; +mod paging; mod prompt; mod select; mod theme; pub use multi_select::AmeMultiSelect; +pub use paging::page_string; pub use prompt::AmePrompt; pub use select::AmeFuzzySelect; diff --git a/src/interact/paging.rs b/src/interact/paging.rs new file mode 100644 index 0000000..a5f3b78 --- /dev/null +++ b/src/interact/paging.rs @@ -0,0 +1,18 @@ +use std::env; +use std::fmt::Write; + +use crate::internal::error::AppError; +use crate::internal::error::AppResult; +use crate::with_suspended_output; + +use minus::Pager; + +pub fn page_string(content: S) -> AppResult<()> { + let mut pager = Pager::new(); + pager.set_prompt( + env::args().collect::>().join(" ") + + " | Q: quit | /: Search | n: next result | p: previous result", + )?; + writeln!(pager, "{}", content.to_string())?; + with_suspended_output!({ minus::page_all(pager).map_err(AppError::from) }) +} diff --git a/src/internal/error.rs b/src/internal/error.rs index cde2eab..c9d9ec7 100644 --- a/src/internal/error.rs +++ b/src/internal/error.rs @@ -19,6 +19,8 @@ pub enum AppError { UserCancellation, MissingDependencies(Vec), MakePkg(String), + MinusError(minus::MinusError), + FmtError(std::fmt::Error), } impl Display for AppError { @@ -35,6 +37,8 @@ impl Display for AppError { write!(f, "Missing dependencies {}", deps.join(", ")) } AppError::MakePkg(msg) => write!(f, "Failed to ru makepkg {msg}"), + AppError::MinusError(e) => Display::fmt(e, f), + AppError::FmtError(e) => Display::fmt(e, f), } } } @@ -65,6 +69,18 @@ impl From<&str> for AppError { } } +impl From for AppError { + fn from(e: minus::MinusError) -> Self { + Self::MinusError(e) + } +} + +impl From for AppError { + fn from(e: std::fmt::Error) -> Self { + Self::FmtError(e) + } +} + pub trait SilentUnwrap { fn silent_unwrap(self, error_code: AppExitCode) -> T; } diff --git a/src/main.rs b/src/main.rs index 9c11385..fc17039 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,12 @@ use args::{Args, GenCompArgs, InfoArgs}; use builder::pacman::{PacmanColor, PacmanQueryBuilder}; use clap::Parser; + use internal::commands::ShellCommand; use internal::error::SilentUnwrap; use crate::args::{InstallArgs, Operation, QueryArgs, RemoveArgs, SearchArgs}; +use crate::interact::page_string; use crate::internal::detect; use crate::internal::exit_code::AppExitCode; use crate::internal::{sort, start_sudoloop, structs::Options}; @@ -133,7 +135,10 @@ async fn cmd_search(args: SearchArgs, options: Options) { } else { tracing::info!("Results:"); let list: Vec = results.iter().map(|x| x.to_print_string()).collect(); - get_logger().print_list(list, "\n", 0); + get_logger().print_list(&list, "\n", 0); + if list.join("\n").lines().count() > crossterm::terminal::size().unwrap().1 as usize { + page_string(&list.join("\n")).silent_unwrap(AppExitCode::Other); + } } }