Skip to content
Open
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
2 changes: 2 additions & 0 deletions src/core/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub enum Command {

// Configuration options
SetExitStrategy(ExitStrategy),
PersistAlternate(bool),
SetInputClassifier(Box<dyn InputClassifier + Send + Sync + 'static>),
AddExitCallback(Box<dyn FnMut() + Send + Sync + 'static>),
#[cfg(feature = "static_output")]
Expand Down Expand Up @@ -70,6 +71,7 @@ impl PartialEq for Command {
impl Debug for Command {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::PersistAlternate(persist) => write!(f, "PersistAlternate({persist})"),
Self::SetData(text) => write!(f, "SetData({text:?})"),
Self::AppendData(text) => write!(f, "AppendData({text:?})"),
Self::SetPrompt(text) => write!(f, "SetPrompt({text:?})"),
Expand Down
23 changes: 22 additions & 1 deletion src/core/ev_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn handle_event(
Command::UserInput(InputEvent::Exit) => {
p.exit();
is_exited.store(true, std::sync::atomic::Ordering::SeqCst);
term::cleanup(&mut out, &p.exit_strategy, true)?;
term::cleanup(&mut out, &p.exit_strategy, true, p.persist_alternate)?;
}
Command::UserInput(InputEvent::UpdateUpperMark(mut um)) => {
display::draw_for_change(out, p, &mut um)?;
Expand Down Expand Up @@ -274,6 +274,7 @@ pub fn handle_event(
display::write_prompt(out, &p.displayed_prompt, p.rows.try_into().unwrap())?;
}
Command::SetExitStrategy(es) => p.exit_strategy = es,
Command::PersistAlternate(b) => p.persist_alternate = b,
#[cfg(feature = "static_output")]
Command::SetRunNoOverflow(val) => p.run_no_overflow = val,
#[cfg(feature = "search")]
Expand Down Expand Up @@ -475,6 +476,26 @@ mod tests {
assert_eq!(ps.exit_strategy, ExitStrategy::PagerQuit);
}

#[test]
fn set_persist_screen() {
let mut ps = PagerState::new().unwrap();
let ev = Command::PersistAlternate(true);
let mut out = Vec::new();
let mut command_queue = CommandQueue::new_zero();

handle_event(
ev,
&mut out,
&mut ps,
&mut command_queue,
&Arc::new(AtomicBool::new(false)),
#[cfg(feature = "search")]
&UIA,
)
.unwrap();
assert_eq!(ps.persist_alternate, true);
}

#[test]
fn add_exit_callback() {
let mut ps = PagerState::new().unwrap();
Expand Down
10 changes: 8 additions & 2 deletions src/core/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ pub fn init_core(pager: &Pager, rm: RunMode) -> std::result::Result<(), MinusErr
stdout(),
&crate::ExitStrategy::PagerQuit,
true,
false,
));
panic_hook(pinfo);
}));
Expand Down Expand Up @@ -169,7 +170,7 @@ pub fn init_core(pager: &Pager, rm: RunMode) -> std::result::Result<(), MinusErr
let mut rm = RUNMODE.lock();
*rm = RunMode::Uninitialized;
drop(rm);
term::cleanup(out.as_ref(), &crate::ExitStrategy::PagerQuit, true)?;
term::cleanup(out.as_ref(), &crate::ExitStrategy::PagerQuit, true, false)?;
}
res
});
Expand All @@ -188,7 +189,12 @@ pub fn init_core(pager: &Pager, rm: RunMode) -> std::result::Result<(), MinusErr
let mut rm = RUNMODE.lock();
*rm = RunMode::Uninitialized;
drop(rm);
term::cleanup(out_copy.as_ref(), &crate::ExitStrategy::PagerQuit, true)?;
term::cleanup(
out_copy.as_ref(),
&crate::ExitStrategy::PagerQuit,
true,
false,
)?;
}
res
});
Expand Down
11 changes: 9 additions & 2 deletions src/core/utils/term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,22 @@ pub fn cleanup(
mut out: impl io::Write,
es: &crate::ExitStrategy,
cleanup_screen: bool,
persist_screen: bool,
) -> std::result::Result<(), CleanupError> {
if cleanup_screen {
// Reverse order of setup.
execute!(out, cursor::Show).map_err(|e| CleanupError::ShowCursor(e.into()))?;
terminal::disable_raw_mode().map_err(|e| CleanupError::DisableRawMode(e.into()))?;
execute!(out, event::DisableMouseCapture)
.map_err(|e| CleanupError::DisableMouseCapture(e.into()))?;
execute!(out, terminal::LeaveAlternateScreen)
.map_err(|e| CleanupError::LeaveAlternateScreen(e.into()))?;
if !persist_screen {
execute!(out, terminal::LeaveAlternateScreen)
.map_err(|e| CleanupError::LeaveAlternateScreen(e.into()))?;
} else {
// Clear out the pager line, it's not something you'd want to keep
queue!(out, Clear(terminal::ClearType::CurrentLine)).unwrap();
out.flush().unwrap();
}
}

if *es == crate::ExitStrategy::ProcessQuit {
Expand Down
9 changes: 9 additions & 0 deletions src/pager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,15 @@ impl Pager {
Ok(self.tx.send(Command::SetExitStrategy(es))?)
}

/// Set if minus persists the alternate screen buffer on exit.
///
/// This controls how the pager will behave with regards to clearing the screen when
/// the user presses `q` or `Ctrl+C'. If it is set, instead of clearing the screen
/// when exited, it will continue to show.
pub fn persist_alternate_screen(&self, b: bool) -> Result<(), MinusError> {
Ok(self.tx.send(Command::PersistAlternate(b))?)
}

/// Set whether to display pager if there's less data than
/// available screen height
///
Expand Down
4 changes: 4 additions & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ pub struct PagerState {
/// The behaviour to do when user quits the program using `q` or `Ctrl+C`
/// See [`ExitStrategy`] for available options
pub(crate) exit_strategy: ExitStrategy,
/// The behaviour to do when user quits the program using `q` or `Ctrl+C`
/// See [persist_alternate_screen](crate::pager::Pager::persist_alternate_screen) for more info.
pub(crate) persist_alternate: bool,
/// The prompt that should be displayed to the user, formatted with the
/// current search index and number of matches (if the search feature is enabled),
/// and the current numbers inputted to scroll
Expand Down Expand Up @@ -194,6 +197,7 @@ impl PagerState {
prompt,
running: &minus_core::RUNMODE,
exit_strategy: ExitStrategy::ProcessQuit,
persist_alternate: false,
input_classifier: Box::<HashedEventRegister<RandomState>>::default(),
exit_callbacks: Vec::with_capacity(5),
message: None,
Expand Down