Skip to content

Commit

Permalink
Add ClearOffset to replicate macOS Cmd+K behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
fcoury committed Oct 8, 2023
1 parent efca21a commit 63f36a5
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 0 deletions.
1 change: 1 addition & 0 deletions zellij-client/src/input_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ impl InputHandler {
},
Action::CloseFocus
| Action::ClearScreen
| Action::ClearScrollback(_)
| Action::NewPane(..)
| Action::Run(_)
| Action::NewTiledPane(..)
Expand Down
26 changes: 26 additions & 0 deletions zellij-server/src/panes/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,32 @@ impl Grid {
self.reset_terminal_state();
self.mark_for_rerender();
}
/// Clears the scrollback and positions the current active line on top of the pane.
pub fn clear_scrollback(&mut self, offset: i32) {
if self.alternate_screen_state.is_some() {
log::warn!("Tried to clear scrollback of pane with alternate_screen_state");
return;
}

let new_viewport = self
.viewport
.clone()
.into_iter()
.skip(self.viewport.len().saturating_sub(offset as usize + 1))
.collect::<Vec<_>>();

self.clear_viewport_before_rendering = true;
self.lines_above = VecDeque::new();
self.lines_below = vec![];
self.viewport = vec![Row::new().canonical()];
self.scroll_region = None;
self.scrollback_buffer_lines = 0;
self.viewport = new_viewport;
self.cursor.y = offset as usize;
self.output_buffer.update_all_lines();

self.mark_for_rerender();
}
/// Dumps all lines above terminal vieport and the viewport itself to a string
pub fn dump_screen(&mut self, full: bool) -> String {
let viewport: String = dump_screen!(self.viewport);
Expand Down
3 changes: 3 additions & 0 deletions zellij-server/src/panes/plugin_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,9 @@ impl Pane for PluginPane {
fn clear_scroll(&mut self) {
// noop
}
fn clear_scrollback(&mut self, _offset: i32) {
// noop
}
fn start_selection(&mut self, start: &Position, client_id: ClientId) {
self.send_plugin_instructions
.send(PluginInstruction::Update(vec![(
Expand Down
3 changes: 3 additions & 0 deletions zellij-server/src/panes/terminal_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@ impl Pane for TerminalPane {
fn clear_screen(&mut self) {
self.grid.clear_screen()
}
fn clear_scrollback(&mut self, offset: i32) {
self.grid.clear_scrollback(offset)
}
fn scroll_up(&mut self, count: usize, _client_id: ClientId) {
self.grid.move_viewport_up(count);
self.set_should_render(true);
Expand Down
12 changes: 12 additions & 0 deletions zellij-server/src/plugins/zellij_exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,18 @@ fn clear_screen(env: &ForeignFunctionEnv) {
let action = Action::ClearScreen;
apply_action!(action, error_msg, env);
}

fn clear_scrollback(env: &ForeignFunctionEnv, offset: i32) {
let error_msg = || {
format!(
"failed to clear scrollback in plugin {}",
env.plugin_env.name()
)
};
let action = Action::ClearScrollback(offset);
apply_action!(action, error_msg, env);
}

fn scroll_up(env: &ForeignFunctionEnv) {
let error_msg = || format!("failed to scroll up in plugin {}", env.plugin_env.name());
let action = Action::ScrollUp;
Expand Down
5 changes: 5 additions & 0 deletions zellij-server/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ pub(crate) fn route_action(
.send_to_screen(ScreenInstruction::ClearScreen(client_id))
.with_context(err_context)?;
},
Action::ClearScrollback(offset) => {
senders
.send_to_screen(ScreenInstruction::ClearScrollback(client_id, offset))
.with_context(err_context)?;
},
Action::DumpScreen(val, full) => {
senders
.send_to_screen(ScreenInstruction::DumpScreen(val, client_id, full))
Expand Down
15 changes: 15 additions & 0 deletions zellij-server/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ pub enum ScreenInstruction {
MovePaneLeft(ClientId),
Exit,
ClearScreen(ClientId),
ClearScrollback(ClientId, i32),
DumpScreen(String, ClientId, bool),
EditScrollback(ClientId),
ScrollUp(ClientId),
Expand Down Expand Up @@ -366,6 +367,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::MovePaneLeft(..) => ScreenContext::MovePaneLeft,
ScreenInstruction::Exit => ScreenContext::Exit,
ScreenInstruction::ClearScreen(..) => ScreenContext::ClearScreen,
ScreenInstruction::ClearScrollback(..) => ScreenContext::ClearScrollback,
ScreenInstruction::DumpScreen(..) => ScreenContext::DumpScreen,
ScreenInstruction::EditScrollback(..) => ScreenContext::EditScrollback,
ScreenInstruction::ScrollUp(..) => ScreenContext::ScrollUp,
Expand Down Expand Up @@ -2247,6 +2249,19 @@ pub(crate) fn screen_thread_main(
screen.render()?;
screen.unblock_input()?;
},
ScreenInstruction::ClearScrollback(client_id, offset) => {
active_tab_and_connected_client_id!(
screen,
client_id,
|tab: &mut Tab, client_id: ClientId| tab.clear_scrollback_active_terminal_screen(
client_id,
offset,
),
?
);
screen.render()?;
screen.unblock_input()?;
},
ScreenInstruction::DumpScreen(file, client_id, full) => {
active_tab_and_connected_client_id!(
screen,
Expand Down
11 changes: 11 additions & 0 deletions zellij-server/src/tab/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ pub trait Pane {
fn pull_left(&mut self, count: usize);
fn pull_up(&mut self, count: usize);
fn clear_screen(&mut self);
fn clear_scrollback(&mut self, offset: i32);
fn dump_screen(&mut self, _client_id: ClientId, _full: bool) -> String {
"".to_owned()
}
Expand Down Expand Up @@ -2503,6 +2504,16 @@ impl Tab {
}
Ok(())
}
pub fn clear_scrollback_active_terminal_screen(
&mut self,
client_id: ClientId,
offset: i32,
) -> Result<()> {
if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) {
active_pane.clear_scrollback(offset);
}
Ok(())
}
pub fn dump_active_terminal_screen(
&mut self,
file: Option<String>,
Expand Down
5 changes: 5 additions & 0 deletions zellij-utils/assets/prost/api.action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ pub mod action {
RenamePluginPanePayload(super::IdAndName),
#[prost(message, tag = "44")]
RenameTabPayload(super::IdAndName),
#[prost(message, tag = "45")]
ClearScrollbackPayload(i32),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
Expand Down Expand Up @@ -400,6 +402,7 @@ pub enum ActionName {
BreakPane = 77,
BreakPaneRight = 78,
BreakPaneLeft = 79,
ClearScrollback = 80,
}
impl ActionName {
/// String value of the enum field names used in the ProtoBuf definition.
Expand All @@ -422,6 +425,7 @@ impl ActionName {
ActionName::MovePane => "MovePane",
ActionName::MovePaneBackwards => "MovePaneBackwards",
ActionName::ClearScreen => "ClearScreen",
ActionName::ClearScrollback => "ClearScrollback",
ActionName::DumpScreen => "DumpScreen",
ActionName::EditScrollback => "EditScrollback",
ActionName::ScrollUp => "ScrollUp",
Expand Down Expand Up @@ -507,6 +511,7 @@ impl ActionName {
"MovePane" => Some(Self::MovePane),
"MovePaneBackwards" => Some(Self::MovePaneBackwards),
"ClearScreen" => Some(Self::ClearScreen),
"ClearScrollback" => Some(Self::ClearScrollback),
"DumpScreen" => Some(Self::DumpScreen),
"EditScrollback" => Some(Self::EditScrollback),
"ScrollUp" => Some(Self::ScrollUp),
Expand Down
6 changes: 6 additions & 0 deletions zellij-utils/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,12 @@ pub enum CliAction {
MovePaneBackwards,
/// Clear all buffers for a focused pane
Clear,
/// Clear the scrollback and positions the current active line on top of the pane.
ClearScrollback {
/// Offset of lines from the current viewport to keep
#[clap(short, long, value_parser, default_value("1"))]
offset: i8,
},
/// Dump the focused pane to a file
DumpScreen {
path: PathBuf,
Expand Down
1 change: 1 addition & 0 deletions zellij-utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ pub enum ScreenContext {
MovePaneLeft,
Exit,
ClearScreen,
ClearScrollback,
DumpScreen,
EditScrollback,
ScrollUp,
Expand Down
5 changes: 5 additions & 0 deletions zellij-utils/src/input/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ pub enum Action {
MovePaneBackwards,
/// Clear all buffers of a current screen
ClearScreen,
/// Clear the scrollback and positions the current active line on top of the pane.
ClearScrollback(i32),
/// Dumps the screen to a file
DumpScreen(String, bool),
/// Scroll up in focus pane.
Expand Down Expand Up @@ -276,6 +278,9 @@ impl Action {
CliAction::MovePane { direction } => Ok(vec![Action::MovePane(direction)]),
CliAction::MovePaneBackwards => Ok(vec![Action::MovePaneBackwards]),
CliAction::Clear => Ok(vec![Action::ClearScreen]),
CliAction::ClearScrollback { offset } => {
Ok(vec![Action::ClearScrollback(offset as i32)])
},
CliAction::DumpScreen { path, full } => Ok(vec![Action::DumpScreen(
path.as_os_str().to_string_lossy().into(),
full,
Expand Down
13 changes: 13 additions & 0 deletions zellij-utils/src/kdl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,16 @@ impl Action {
})? as u32;
Ok(Action::GoToTab(tab_index))
},
"ClearScrollback" => {
let offset = *bytes.get(0).ok_or_else(|| {
ConfigError::new_kdl_error(
format!("Missing scrollback offset"),
action_node.span().offset(),
action_node.span().len(),
)
})? as u32;
Ok(Action::ClearScrollback(offset as i32))
},
_ => Err(ConfigError::new_kdl_error(
"Failed to parse action".into(),
action_node.span().offset(),
Expand Down Expand Up @@ -703,6 +713,9 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
"Detach" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"Copy" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"Clear" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"ClearScrollback" => {
parse_kdl_action_u8_arguments!(action_name, action_arguments, kdl_action)
},
"Confirm" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"Deny" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"Write" => parse_kdl_action_u8_arguments!(action_name, action_arguments, kdl_action),
Expand Down
4 changes: 4 additions & 0 deletions zellij-utils/src/plugin_api/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,10 @@ impl TryFrom<Action> for ProtobufAction {
name: ProtobufActionName::ClearScreen as i32,
optional_payload: None,
}),
Action::ClearScrollback(offset) => Ok(ProtobufAction {
name: ProtobufActionName::ClearScrollback as i32,
optional_payload: Some(OptionalPayload::ClearScrollbackPayload(offset)),
}),
Action::DumpScreen(file_path, include_scrollback) => Ok(ProtobufAction {
name: ProtobufActionName::DumpScreen as i32,
optional_payload: Some(OptionalPayload::DumpScreenPayload(DumpScreenPayload {
Expand Down

0 comments on commit 63f36a5

Please sign in to comment.