Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edit scrollback #1456

Merged
merged 22 commits into from
Jun 6, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
38c64f4
initial commit for opening the current buffer in an editor
cosminadrianpopescu Jun 3, 2022
d9a677a
fix(editor): take hidden panes into consideration when manipulating t…
imsnif Jun 4, 2022
24d7f93
when closing an edit buffer, take the geometry of the replaced buffer…
cosminadrianpopescu Jun 4, 2022
8ab2d67
if the floating panels are displayed, don't add to hidden panels the …
cosminadrianpopescu Jun 4, 2022
c52a203
strategy changing - put the panels inside a suppressed_panels HashMap…
cosminadrianpopescu Jun 4, 2022
487ea65
Revert "strategy changing - put the panels inside a suppressed_panels…
cosminadrianpopescu Jun 4, 2022
97836d7
remove the floating panes by moving them to the tiled_panes in hidden…
cosminadrianpopescu Jun 4, 2022
a532344
feat(edit): open editor to correct line and don't crash when none is set
imsnif Jun 5, 2022
98d7f20
Merge branch 'edit-scrollback' of github.com:cosminadrianpopescu/zell…
imsnif Jun 5, 2022
9c02f07
formatting
cosminadrianpopescu Jun 5, 2022
95eb12d
feat(edit): use suppressed panes
imsnif Jun 5, 2022
d791eeb
style(fmt): rustfmt and logs
imsnif Jun 5, 2022
f641e25
style(fmt): clean up unused code
imsnif Jun 5, 2022
d06f976
test(editor): integration test for suppressing/closing suppressed pane
imsnif Jun 5, 2022
790530f
test(e2e): editor e2e test
imsnif Jun 5, 2022
e05ac26
style(fmt): rustfmt
imsnif Jun 5, 2022
542d1aa
feat(edit): update ui and setup
imsnif Jun 5, 2022
5ebd5ed
style(fmt): rustfmt
imsnif Jun 5, 2022
c74394c
feat(config): allow configuring scrollback_editor explicitly
imsnif Jun 5, 2022
86f5ea0
style(fmt): rustfmt
imsnif Jun 5, 2022
f240746
Merge branch 'main' into edit-scrollback
imsnif Jun 5, 2022
908800d
chore(repo): build after merging
imsnif Jun 5, 2022
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
Next Next commit
initial commit for opening the current buffer in an editor
  • Loading branch information
cosminadrianpopescu committed Jun 3, 2022
commit 38c64f42ad581c678474b39b9ba078e621d7f373
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs/MANPAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ ACTIONS
* __MoveFocus: <Direction\>__ - moves focus in the specified direction (Left,
Right, Up, Down).
* __DumpScreen: <File\>__ - dumps the screen in the specified file.
* __EditScrollback__ - replaces the current pane with the scrollback buffer.
* __ScrollUp__ - scrolls up 1 line in the focused pane.
* __ScrollDown__ - scrolls down 1 line in the focused pane.
* __PageScrollUp__ - scrolls up 1 page in the focused pane.
Expand Down
1 change: 1 addition & 0 deletions zellij-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ typetag = "0.1.7"
chrono = "0.4.19"
close_fds = "0.3.2"
sysinfo = "0.22.5"
uuid = { version = "0.8.2", features = ["serde", "v4"] }

[dev-dependencies]
insta = "1.6.0"
Expand Down
6 changes: 6 additions & 0 deletions zellij-server/src/panes/tiled_panes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,12 @@ impl TiledPanes {
pub fn panes_to_hide_count(&self) -> usize {
self.panes_to_hide.len()
}
pub fn add_to_hidden_panels(&mut self, pid: PaneId) {
self.panes_to_hide.insert(pid);
}
pub fn remove_from_hidden_panels(&mut self, pid: PaneId) {
self.panes_to_hide.remove(&pid);
}
}

#[allow(clippy::borrowed_box)]
Expand Down
14 changes: 14 additions & 0 deletions zellij-server/src/pty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub enum ClientOrTabIndex {
#[derive(Clone, Debug)]
pub(crate) enum PtyInstruction {
SpawnTerminal(Option<TerminalAction>, ClientOrTabIndex),
OpenInPlaceEditor(PathBuf, ClientId),
SpawnTerminalVertically(Option<TerminalAction>, ClientId),
SpawnTerminalHorizontally(Option<TerminalAction>, ClientId),
UpdateActivePane(Option<PaneId>, ClientId),
Expand All @@ -55,6 +56,7 @@ impl From<&PtyInstruction> for PtyContext {
fn from(pty_instruction: &PtyInstruction) -> Self {
match *pty_instruction {
PtyInstruction::SpawnTerminal(..) => PtyContext::SpawnTerminal,
PtyInstruction::OpenInPlaceEditor(..) => PtyContext::OpenInPlaceEditor,
PtyInstruction::SpawnTerminalVertically(..) => PtyContext::SpawnTerminalVertically,
PtyInstruction::SpawnTerminalHorizontally(..) => PtyContext::SpawnTerminalHorizontally,
PtyInstruction::UpdateActivePane(..) => PtyContext::UpdateActivePane,
Expand Down Expand Up @@ -92,6 +94,18 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<LayoutFromYaml>) {
))
.unwrap();
}
PtyInstruction::OpenInPlaceEditor(temp_file, client_id) => {
let name = String::from(temp_file.to_string_lossy());
let pid = pty.spawn_terminal(Some(TerminalAction::OpenFile(temp_file)), ClientOrTabIndex::ClientId(client_id));
pty.bus
.senders
.send_to_screen(ScreenInstruction::OpenInPlaceEditor(
PaneId::Terminal(pid),
name,
client_id,
))
.unwrap();
}
PtyInstruction::SpawnTerminalVertically(terminal_action, client_id) => {
let pid =
pty.spawn_terminal(terminal_action, ClientOrTabIndex::ClientId(client_id));
Expand Down
6 changes: 6 additions & 0 deletions zellij-server/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ fn route_action(
.send_to_screen(ScreenInstruction::DumpScreen(val, client_id))
.unwrap();
}
Action::EditScrollback => {
session
.senders
.send_to_screen(ScreenInstruction::EditScrollback(client_id))
.unwrap();
}
Action::ScrollUp => {
session
.senders
Expand Down
75 changes: 75 additions & 0 deletions zellij-server/src/screen.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//! Things related to [`Screen`]s.

use zellij_utils::pane_size::Dimension;
use zellij_utils::pane_size::PaneGeom;
use std::collections::HashMap;
use std::cell::RefCell;
use std::collections::{BTreeMap, HashSet};
use std::os::unix::io::RawFd;
Expand All @@ -17,6 +20,20 @@ use zellij_utils::{
use crate::panes::alacritty_functions::xparse_color;
use crate::panes::terminal_character::AnsiCode;

macro_rules! resize_pty {
($pane:expr, $os_input:expr) => {
if let PaneId::Terminal(ref pid) = $pane.pid() {
// FIXME: This `set_terminal_size_using_fd` call would be best in
// `TerminalPane::reflow_lines`
$os_input.set_terminal_size_using_fd(
*pid,
$pane.get_content_columns() as u16,
$pane.get_content_rows() as u16,
);
}
};
}

use crate::{
output::Output,
panes::PaneId,
Expand All @@ -40,6 +57,7 @@ pub enum ScreenInstruction {
PtyBytes(RawFd, VteBytes),
Render,
NewPane(PaneId, ClientOrTabIndex),
OpenInPlaceEditor(PaneId, String, ClientId),
TogglePaneEmbedOrFloating(ClientId),
ToggleFloatingPanes(ClientId, Option<TerminalAction>),
HorizontalSplit(PaneId, ClientId),
Expand Down Expand Up @@ -67,6 +85,7 @@ pub enum ScreenInstruction {
MovePaneLeft(ClientId),
Exit,
DumpScreen(String, ClientId),
EditScrollback(ClientId),
ScrollUp(ClientId),
ScrollUpAt(Position, ClientId),
ScrollDown(ClientId),
Expand Down Expand Up @@ -115,6 +134,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::PtyBytes(..) => ScreenContext::HandlePtyBytes,
ScreenInstruction::Render => ScreenContext::Render,
ScreenInstruction::NewPane(..) => ScreenContext::NewPane,
ScreenInstruction::OpenInPlaceEditor(..) => ScreenContext::OpenInPlaceEditor,
ScreenInstruction::TogglePaneEmbedOrFloating(..) => {
ScreenContext::TogglePaneEmbedOrFloating
}
Expand Down Expand Up @@ -148,6 +168,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::MovePaneLeft(..) => ScreenContext::MovePaneLeft,
ScreenInstruction::Exit => ScreenContext::Exit,
ScreenInstruction::DumpScreen(..) => ScreenContext::DumpScreen,
ScreenInstruction::EditScrollback(..) => ScreenContext::EditScrollback,
ScreenInstruction::ScrollUp(..) => ScreenContext::ScrollUp,
ScreenInstruction::ScrollDown(..) => ScreenContext::ScrollDown,
ScreenInstruction::ScrollToBottom(..) => ScreenContext::ScrollToBottom,
Expand Down Expand Up @@ -798,6 +819,7 @@ pub(crate) fn screen_thread_main(
client_attributes: ClientAttributes,
config_options: Box<Options>,
) {
let mut scrollbacks: HashMap<String, PaneId> = HashMap::new();
let capabilities = config_options.simplified_ui;
let draw_pane_frames = config_options.pane_frames.unwrap_or(true);
let session_is_mirrored = config_options.mirror_session.unwrap_or(false);
Expand Down Expand Up @@ -867,6 +889,50 @@ pub(crate) fn screen_thread_main(

screen.render();
}
ScreenInstruction::OpenInPlaceEditor(pid, file_name, client_id) => {
let mut original_pid: PaneId = pid;
let mut geom: PaneGeom = PaneGeom {x: 0, y: 0, rows: Dimension::percent(100.0), cols: Dimension::percent(100.0)};
if let Some(active_tab) = screen.get_active_tab_mut(client_id) {
if let Some(pane1) = active_tab.get_active_pane(client_id) {
original_pid = pane1.pid();
scrollbacks.insert(file_name, pane1.pid());
geom = pane1.current_geom().clone();
active_tab.create_pane(pid, Some(client_id), geom);
if active_tab.are_floating_panes_visible() {
if let Some(pane2) = active_tab.get_active_pane_mut(client_id) {
pane2.set_geom(geom);
}
else {
log::error!("New editor pane not found. Maybe there is an issue with launching it?: {:?}", client_id);
return ;
}
}
}
else {
log::error!("Could not find the active pane for {:?}", client_id);
return
}
} else {
log::error!("Active tab not found for client id: {:?}", client_id);
return ;
}
if let Some(active_tab) = screen.get_active_tab_mut(client_id) {
active_tab.save_replaced_pane_id(original_pid, client_id, geom);
}
if let Some(active_tab) = screen.get_active_tab(client_id) {
if let Some(pane) = active_tab.get_active_pane(client_id) {
resize_pty!(pane, screen.bus.os_input.as_ref().unwrap().clone());
}
}
screen
.bus
.senders
.send_to_server(ServerInstruction::UnblockInputThread)
.unwrap();
screen.update_tabs();

screen.render();
}
ScreenInstruction::TogglePaneEmbedOrFloating(client_id) => {
if let Some(active_tab) = screen.get_active_tab_mut(client_id) {
active_tab.toggle_pane_embed_or_floating(client_id);
Expand Down Expand Up @@ -1079,6 +1145,15 @@ pub(crate) fn screen_thread_main(

screen.render();
}
ScreenInstruction::EditScrollback(client_id) => {
if let Some(active_tab) = screen.get_active_tab_mut(client_id) {
active_tab.edit_scrollback(client_id);
} else {
log::error!("Active tab not found for client id: {:?}", client_id);
}

screen.render();
}
ScreenInstruction::ScrollUp(client_id) => {
if let Some(active_tab) = screen.get_active_tab_mut(client_id) {
active_tab.scroll_active_terminal_up(client_id);
Expand Down
68 changes: 68 additions & 0 deletions zellij-server/src/tab/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
mod clipboard;
mod copy_command;

use uuid::Uuid;
use std::env::temp_dir;
use copy_command::CopyCommand;
use zellij_tile::prelude::Style;
use zellij_utils::position::{Column, Line};
Expand Down Expand Up @@ -64,12 +66,19 @@ pub const MIN_TERMINAL_WIDTH: usize = 5;

const MAX_PENDING_VTE_EVENTS: usize = 7000;

struct ReplacedPaneInfo {
pub pid: PaneId,
pub client_id: ClientId,
pub geom: PaneGeom
}

pub(crate) struct Tab {
pub index: usize,
pub position: usize,
pub name: String,
tiled_panes: TiledPanes,
floating_panes: FloatingPanes,
replaced_panes: HashMap<PaneId, ReplacedPaneInfo>,
max_panes: Option<usize>,
viewport: Rc<RefCell<Viewport>>, // includes all non-UI panes
display_area: Rc<RefCell<Size>>, // includes all panes (including eg. the status bar and tab bar in the default layout)
Expand Down Expand Up @@ -339,6 +348,7 @@ impl Tab {
position,
tiled_panes,
floating_panes,
replaced_panes: HashMap::new(),
name,
max_panes,
viewport,
Expand Down Expand Up @@ -691,6 +701,34 @@ impl Tab {
}
}
}
pub fn create_pane(&mut self, pid: PaneId, client_id: Option<ClientId>, geom: PaneGeom) {
if self.floating_panes.panes_are_visible() {
self.new_pane(pid, client_id);
} else {
if self.tiled_panes.fullscreen_is_active() {
self.tiled_panes.unset_fullscreen();
}
if let PaneId::Terminal(term_pid) = pid {
let next_terminal_position = self.get_next_terminal_position();
let new_terminal = TerminalPane::new(
term_pid,
geom, // the initial size will be set later
self.style,
next_terminal_position,
String::new(),
self.link_handler.clone(),
self.character_cell_size.clone(),
self.terminal_emulator_colors.clone(),
);
self.tiled_panes.add_pane_with_existing_geom(pid, Box::new(new_terminal));
// self.tiled_panes.insert_pane(pid, Box::new(new_terminal));
// self.should_clear_display_before_rendering = true;
if let Some(client_id) = client_id {
self.tiled_panes.focus_pane(pid, client_id);
}
}
}
}
pub fn horizontal_split(&mut self, pid: PaneId, client_id: ClientId) {
if self.floating_panes.panes_are_visible() {
return;
Expand Down Expand Up @@ -1347,6 +1385,9 @@ impl Tab {
}
pub fn close_pane(&mut self, id: PaneId) -> Option<Box<dyn Pane>> {
if self.floating_panes.panes_contain(&id) {
if self.replaced_panes.contains_key(&id) {
self.replaced_panes.remove(&id);
}
let closed_pane = self.floating_panes.remove_pane(id);
self.floating_panes.move_clients_out_of_pane(id);
if !self.floating_panes.has_panes() {
Expand All @@ -1360,6 +1401,16 @@ impl Tab {
self.tiled_panes.unset_fullscreen();
}
let closed_pane = self.tiled_panes.remove_pane(id);
if self.replaced_panes.contains_key(&id) {
if let Some(info) = self.replaced_panes.get(&id) {
self.tiled_panes.remove_from_hidden_panels((*info).pid);
self.tiled_panes.focus_pane((*info).pid, (*info).client_id);
// if let Some(pane) = self.tiled_panes.get_pane_mut((*info).pid) {
// resize_pty!(pane, self.os_api);
// pane.set_geom((*info).geom);
// }
}
}
self.set_force_render();
self.tiled_panes.set_force_render();
closed_pane
Expand Down Expand Up @@ -1388,6 +1439,17 @@ impl Tab {
self.os_api.write_to_file(dump, file);
}
}
pub fn edit_scrollback(&mut self, client_id: ClientId) {
let mut file = temp_dir();
file.push(format!("{}.dump", Uuid::new_v4()));
self.dump_active_terminal_screen(Some(String::from(file.to_string_lossy())), client_id);
self.senders
.send_to_pty(PtyInstruction::OpenInPlaceEditor(
file,
client_id,
))
.unwrap();
}
pub fn scroll_active_terminal_up(&mut self, client_id: ClientId) {
if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) {
active_pane.scroll_up(1, client_id);
Expand Down Expand Up @@ -1817,6 +1879,12 @@ impl Tab {
pub fn panes_to_hide_count(&self) -> usize {
self.tiled_panes.panes_to_hide_count()
}
pub fn save_replaced_pane_id(&mut self, pid: PaneId, client_id: ClientId, geom: PaneGeom) {
if let Some(scrollback_pane_id) = self.get_active_pane_id(client_id) {
self.replaced_panes.insert(scrollback_pane_id, ReplacedPaneInfo {pid: pid, client_id: client_id, geom: geom});
}
self.tiled_panes.add_to_hidden_panels(pid);
}
}

#[cfg(test)]
Expand Down
3 changes: 3 additions & 0 deletions zellij-utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ pub enum ScreenContext {
HandlePtyBytes,
Render,
NewPane,
OpenInPlaceEditor,
ToggleFloatingPanes,
TogglePaneEmbedOrFloating,
HorizontalSplit,
Expand Down Expand Up @@ -243,6 +244,7 @@ pub enum ScreenContext {
MovePaneLeft,
Exit,
DumpScreen,
EditScrollback,
ScrollUp,
ScrollUpAt,
ScrollDown,
Expand Down Expand Up @@ -292,6 +294,7 @@ pub enum ScreenContext {
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum PtyContext {
SpawnTerminal,
OpenInPlaceEditor,
SpawnTerminalVertically,
SpawnTerminalHorizontally,
UpdateActivePane,
Expand Down
Loading