Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ thiserror = "^1"
regex = { version = "^1", optional = true }
crossbeam-channel = "^0.5"
parking_lot = "0.12.1"
once_cell = { version = "^1.18", features = ["parking_lot"] }

[features]
search = [ "regex" ]
Expand Down
6 changes: 3 additions & 3 deletions Justfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
_prechecks:
-cargo hack 2> /dev/null

if [ $? == 101 ]; then \
if [ $? -eq 101 ]; then \
cargo install cargo-hack; \
fi

Expand All @@ -25,7 +25,7 @@ examples:
cargo check --example=less-rs --features=dynamic_output,search

lint: _prechecks
cargo hack --feature-powerset clippy
cargo hack --feature-powerset clippy --all-targets

verify-all: check-fmt build tests examples lint
@echo "Ready to go"
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ And the help from these projects:-
- [regex](https://crates.io/crates/regex): Regex support when searching.
- [crossbeam-channel](https://crates.io/crates/crossbeam-channel): MPMC channel
- [parking_lot](https://crates.io/crates/parking_lot): Improved atomic storage types
- [once_cell](https://crates.io/crates/once_cell): Provides one-time initialization types.
- [tokio](https://crates.io/crates/tokio): Provides runtime for async examples.

## Get in touch
Expand Down
2 changes: 1 addition & 1 deletion examples/large_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fn main() -> Result<(), MinusError> {

for i in 0..30 {
for _ in 0..=10 {
output.push_str(&format!("{}. Hello ", i))?;
output.push_str(format!("{}. Hello ", i))?;
}
output.push_str("\n")?;
}
Expand Down
2 changes: 1 addition & 1 deletion examples/msg-tokio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ async fn main() -> Result<(), MinusError> {

let increment = async {
for i in 0..=10_u32 {
output.push_str(&format!("{}\n", i))?;
output.push_str(format!("{}\n", i))?;
sleep(Duration::from_millis(100)).await;
}
output.send_message("No more output to come")?;
Expand Down
2 changes: 1 addition & 1 deletion examples/static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ fn main() -> Result<(), MinusError> {
let output = minus::Pager::new();

for i in 0..=100 {
output.push_str(&format!("{}\n", i))?;
output.push_str(format!("{}\n", i))?;
}

minus::page_all(output)?;
Expand Down
14 changes: 7 additions & 7 deletions src/core/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ impl PartialEq for Command {
impl Debug for Command {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::SetData(text) => write!(f, "SetData({:?})", text),
Self::AppendData(text) => write!(f, "AppendData({:?})", text),
Self::SetPrompt(text) => write!(f, "SetPrompt({:?})", text),
Self::SendMessage(text) => write!(f, "SendMessage({:?})", text),
Self::SetLineNumbers(ln) => write!(f, "SetLineNumbers({:?})", ln),
Self::LineWrapping(lw) => write!(f, "LineWrapping({:?})", lw),
Self::SetExitStrategy(es) => write!(f, "SetExitStrategy({:?})", es),
Self::SetData(text) => write!(f, "SetData({text:?})"),
Self::AppendData(text) => write!(f, "AppendData({text:?})"),
Self::SetPrompt(text) => write!(f, "SetPrompt({text:?})"),
Self::SendMessage(text) => write!(f, "SendMessage({text:?})"),
Self::SetLineNumbers(ln) => write!(f, "SetLineNumbers({ln:?})"),
Self::LineWrapping(lw) => write!(f, "LineWrapping({lw:?})"),
Self::SetExitStrategy(es) => write!(f, "SetExitStrategy({es:?})"),
Self::SetInputClassifier(_) => write!(f, "SetInputClassifier"),
Self::ShowPrompt(show) => write!(f, "ShowPrompt({show:?})"),
Self::FormatRedrawPrompt => write!(f, "FormatRedrawPrompt"),
Expand Down
17 changes: 8 additions & 9 deletions src/core/ev_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,9 @@ pub fn handle_event(

Command::SetPrompt(ref text) | Command::SendMessage(ref text) => {
if let Command::SetPrompt(_) = ev {
p.prompt = text.to_string();
p.prompt = text.clone();
} else {
p.message = Some(text.to_string());
p.message = Some(text.clone());
}
p.format_prompt();
if !p.running.lock().is_uninitialized() {
Expand Down Expand Up @@ -337,17 +337,16 @@ mod tests {
use super::super::commands::Command;
use super::handle_event;
use crate::{minus_core::CommandQueue, ExitStrategy, PagerState, RunMode};
use std::sync::{atomic::AtomicBool, Arc};
#[cfg(feature = "search")]
use {
once_cell::sync::Lazy,
parking_lot::{Condvar, Mutex},
};
use parking_lot::{Condvar, Mutex};
#[cfg(feature = "search")]
use std::sync::LazyLock;
use std::sync::{atomic::AtomicBool, Arc};

// Tests constants
#[cfg(feature = "search")]
static UIA: Lazy<Arc<(Mutex<bool>, Condvar)>> =
Lazy::new(|| Arc::new((Mutex::new(true), Condvar::new())));
static UIA: LazyLock<Arc<(Mutex<bool>, Condvar)>> =
LazyLock::new(|| Arc::new((Mutex::new(true), Condvar::new())));
const TEST_STR: &str = "This is some sample text";

// Tests for event emitting functions of Pager
Expand Down
20 changes: 10 additions & 10 deletions src/core/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
//!
//! This module provides two main functions:-
//! * The [`init_core`] function which is responsible for setting the initial state of the
//! Pager, do environment checks and initializing various core functions on either async
//! tasks or native threads depending on the feature set
//! Pager, do environment checks and initializing various core functions on either async
//! tasks or native threads depending on the feature set
//!
//! * The [`start_reactor`] function displays the displays the output and also polls
//! the [`Receiver`] held inside the [`Pager`] for events. Whenever a event is
//! detected, it reacts to it accordingly.
//! the [`Receiver`] held inside the [`Pager`] for events. Whenever a event is
//! detected, it reacts to it accordingly.
#[cfg(feature = "static_output")]
use crate::minus_core::utils::display;
use crate::{
Expand Down Expand Up @@ -52,21 +52,21 @@ use super::{utils::display::draw_for_change, CommandQueue, RUNMODE};
///
/// Then it checks if the minus is running in static mode and does some checks:-
/// * If standard output is not a terminal screen, that is if it is a file or block
/// device, minus will write all the data at once to the stdout and quit
/// device, minus will write all the data at once to the stdout and quit
///
/// * If the size of the data is less than the available number of rows in the terminal
/// then it displays everything on the main stdout screen at once and quits. This
/// behaviour can be turned off if [`Pager::set_run_no_overflow(true)`] is called
/// by the main application
/// then it displays everything on the main stdout screen at once and quits. This
/// behaviour can be turned off if [`Pager::set_run_no_overflow(true)`] is called
/// by the main application
// Sorry... this behaviour would have been cool to have in async mode, just think about it!!! Many
// implementations were proposed but none were perfect
// It is because implementing this especially with line wrapping and terminal scrolling
// is a a nightmare because terminals are really naughty and more when you have to fight with it
// using your library... your only weapon
// So we just don't take any more proposals about this. It is really frustating to
// to thoroughly test each implementation and fix out all rough edges around it
/// Next it initializes the runtime and calls [`start_reactor`] and a [`event reader`]` which is
/// selected based on the enabled feature set:-
/// Next it initializes the runtime and calls [`start_reactor`] and a [`event reader`]` which is
/// selected based on the enabled feature set:-
///
/// # Errors
///
Expand Down
2 changes: 1 addition & 1 deletion src/core/utils/display/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub fn draw_append_text(
crossterm::execute!(out, crossterm::terminal::Clear(ClearType::CurrentLine))?;
}
for line in &fmt_text[0..num_appendable] {
write!(out, "{}\n\r", line)?;
write!(out, "{line}\n\r")?;
}
out.flush()?;
}
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub enum MinusError {
#[cfg_attr(docsrs, doc(cfg(feature = "search")))]
SearchExpError(#[from] RegexError),

#[cfg(feature = "tokio")]
#[cfg(test)]
#[error(transparent)]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
JoinError(#[from] tokio::task::JoinError),
Expand Down
7 changes: 3 additions & 4 deletions src/input/definitions/keydefs.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#![allow(dead_code)]

use super::{Token, MODIFIERS};
use std::collections::HashMap;
use std::{collections::HashMap, sync::LazyLock};

use crossterm::event::{KeyCode, KeyEvent, KeyEventState, KeyModifiers};
use once_cell::sync::Lazy;

static SPECIAL_KEYS: Lazy<HashMap<&str, KeyCode>> = Lazy::new(|| {
static SPECIAL_KEYS: LazyLock<HashMap<&str, KeyCode>> = LazyLock::new(|| {
let mut map = HashMap::new();

map.insert("enter", KeyCode::Enter);
Expand Down Expand Up @@ -100,7 +99,7 @@ impl KeySeq {
}
}
Token::MultipleChar(c) => {
let c = c.to_ascii_lowercase().to_string();
let c = c.to_ascii_lowercase().clone();
SPECIAL_KEYS.get(c.as_str()).map_or_else(
|| panic!("'{}': Invalid key input sequence given", text),
|key| {
Expand Down
7 changes: 3 additions & 4 deletions src/input/definitions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ pub mod keydefs;
pub mod mousedefs;

use crossterm::event::KeyModifiers;
use once_cell::sync::Lazy;
use std::collections::HashMap;
use std::{collections::HashMap, sync::LazyLock};

fn parse_tokens(mut text: &str) -> Vec<Token> {
assert!(
text.chars().all(|c| c.is_ascii()),
text.is_ascii(),
"'{}': Non ascii sequence found in input sequence",
text
);
Expand Down Expand Up @@ -52,7 +51,7 @@ fn parse_tokens(mut text: &str) -> Vec<Token> {
token_list
}

pub static MODIFIERS: Lazy<HashMap<char, KeyModifiers>> = Lazy::new(|| {
pub static MODIFIERS: LazyLock<HashMap<char, KeyModifiers>> = LazyLock::new(|| {
let mut map = HashMap::new();
map.insert('m', KeyModifiers::ALT);
map.insert('c', KeyModifiers::CONTROL);
Expand Down
7 changes: 3 additions & 4 deletions src/input/definitions/mousedefs.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::collections::HashMap;
use std::{collections::HashMap, sync::LazyLock};

use super::{Token, MODIFIERS};
use crossterm::event::{KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
use once_cell::sync::Lazy;

static MOUSE_ACTIONS: Lazy<HashMap<&str, MouseEventKind>> = Lazy::new(|| {
static MOUSE_ACTIONS: LazyLock<HashMap<&str, MouseEventKind>> = LazyLock::new(|| {
let mut map = HashMap::new();

map.insert("left:down", MouseEventKind::Down(MouseButton::Left));
Expand Down Expand Up @@ -68,7 +67,7 @@ fn gen_mouse_event_from_tokenlist(token_list: &[Token], text: &str) -> MouseEven
);
}
Token::MultipleChar(c) => {
let c = c.to_ascii_lowercase().to_string();
let c = c.to_ascii_lowercase().clone();
MOUSE_ACTIONS.get(c.as_str()).map_or_else(
|| panic!("'{}': Invalid key input sequence given", text),
|k| {
Expand Down
14 changes: 9 additions & 5 deletions src/input/hashed_event_register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,15 @@ where
}
}

/// Add all elemnts of `desc` as key bindings that minus should respond to with the callback `cb`
/// Add all elemnts of `desc` as key bindings that minus should respond to with the callback `cb`.
///
/// Prefer using this over [add_key_events](HashedEventRegister::add_key_events).
///
/// # Panics
///
/// This will panic if you the keybinding has been previously defined, unless the `remap`
/// is set to true. This helps preventing accidental overrides of your keybindings.
///
/// Prefer using this over [add_key_events](HashedEventRegister::add_key_events).
///
/// # Example
/// ```should_panic
/// use minus::input::{InputEvent, HashedEventRegister, crossterm_event};
Expand Down Expand Up @@ -308,12 +310,14 @@ where
}
}

/// Add all elemnts of `desc` as mouse bindings that minus should respond to with the callback `cb`
/// Add all elemnts of `desc` as mouse bindings that minus should respond to with the callback `cb`.
///
/// Prefer using this over [add_mouse_events](HashedEventRegister::add_mouse_events).
///
/// # Panics
/// This will panic if you the keybinding has been previously defined, unless the `remap`
/// is set to true. This helps preventing accidental overrides of your keybindings.
///
/// Prefer using this over [add_mouse_events](HashedEventRegister::add_mouse_events).
/// # Example
/// ```should_panic
/// use minus::input::{InputEvent, HashedEventRegister};
Expand Down
2 changes: 1 addition & 1 deletion src/input/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Manage keyboard/mouse-bindings while running `minus`.
//!
//! > **Terminology in this module**: We will call any keyboard/mouse event from the terminal as a **binding**
//! and its associated predefined action as **callback**.
//! > and its associated predefined action as **callback**.
//!
//! There are two ways to define binding in minus as you will see below.
//!
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
//! # Overview
//! When getting started with minus, the two most important concepts to get familier with are:
//! * The [Pager] type: which acts as a bridge between your application and minus. It is used
//! to pass data and configure minus before and after starting the pager.
//! to pass data and configure minus before and after starting the pager.
//! * Initialization functions: This includes the [dynamic_paging] and [page_all] functions which
//! take a [Pager] as argument. They are responsible for generating the initial state and starting
//! the pager.
//! take a [Pager] as argument. They are responsible for generating the initial state and starting
//! the pager.
//!
//! See the docs for the respective items to learn more on its usage.
//!
Expand Down
27 changes: 13 additions & 14 deletions src/screen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl Screen {
/// Get the actual number of physical rows that the text that will actually occupy on the
/// terminal
#[must_use]
pub fn formatted_lines_count(&self) -> usize {
pub const fn formatted_lines_count(&self) -> usize {
self.formatted_lines.len()
}
/// Get the number of [`Lines`](std::str::Lines) in the text.
Expand Down Expand Up @@ -83,7 +83,7 @@ impl Screen {
text: TextBlock,
line_numbers: LineNumbers,
cols: u16,
#[cfg(feature = "search")] search_term: &Option<Regex>,
#[cfg(feature = "search")] search_term: Option<&Regex>,
) -> FormatResult {
// If the last line of self.screen.orig_text is not terminated by than the first line of
// the incoming text is part of that line so we also need to take care of that.
Expand Down Expand Up @@ -259,7 +259,7 @@ where
pub prev_unterminated: usize,
/// Search term if a search is active
#[cfg(feature = "search")]
pub search_term: &'a Option<regex::Regex>,
pub search_term: Option<&'a regex::Regex>,

/// Value of [PagerState::line_wrapping]
pub line_wrapping: bool,
Expand Down Expand Up @@ -335,8 +335,7 @@ where
// * After all the formatting is done, we return the format results.

// Compute the text to be format and set clean_append
let to_format;
if let Some(attached_text) = opts.attachment {
let to_format = if let Some(attached_text) = opts.attachment {
// Tweak certain parameters if we are joining the last line of already present text with the first line of
// incoming text.
//
Expand All @@ -354,10 +353,10 @@ where
s.push_str(attached_text);
s.push_str(opts.text);

to_format = s;
s
} else {
to_format = opts.text.to_string();
}
opts.text.to_string()
};

let lines = to_format
.lines()
Expand Down Expand Up @@ -491,12 +490,12 @@ where
/// - `line`: The line to format
/// - `line_numbers`: tells whether to format the line with line numbers.
/// - `len_line_number`: is the number of digits that number of lines in [`PagerState::lines`] occupy.
/// For example, this will be 2 if number of lines in [`PagerState::lines`] is 50 and 3 if
/// number of lines in [`PagerState::lines`] is 500. This is used for calculating the padding
/// of each displayed line.
/// For example, this will be 2 if number of lines in [`PagerState::lines`] is 50 and 3 if
/// number of lines in [`PagerState::lines`] is 500. This is used for calculating the padding
/// of each displayed line.
/// - `idx`: is the position index where the line is placed in [`PagerState::lines`].
/// - `formatted_idx`: is the position index where the line will be placed in the resulting
/// [`PagerState::formatted_lines`](crate::state::PagerState::formatted_lines)
/// [`PagerState::formatted_lines`](crate::state::PagerState::formatted_lines)
/// - `cols`: Number of columns in the terminal
/// - `search_term`: Contains the regex if a search is active
///
Expand All @@ -512,7 +511,7 @@ pub(crate) fn formatted_line<'a>(
line_wrapping: bool,
#[cfg(feature = "search")] formatted_idx: usize,
#[cfg(feature = "search")] search_idx: &mut BTreeSet<usize>,
#[cfg(feature = "search")] search_term: &Option<regex::Regex>,
#[cfg(feature = "search")] search_term: Option<&regex::Regex>,
) -> Rows {
assert!(
!line.contains('\n'),
Expand Down Expand Up @@ -626,7 +625,7 @@ pub(crate) fn make_format_lines(
line_numbers: LineNumbers,
cols: usize,
line_wrapping: bool,
#[cfg(feature = "search")] search_term: &Option<regex::Regex>,
#[cfg(feature = "search")] search_term: Option<&regex::Regex>,
) -> (Rows, FormatResult) {
let mut buffer = Vec::with_capacity(256);
let format_opts = FormatOpts {
Expand Down
Loading
Loading