Skip to content

Commit

Permalink
store tab history in a stack-like data structure
Browse files Browse the repository at this point in the history
  • Loading branch information
sagittarius-a committed Aug 3, 2021
1 parent 38f0c7a commit 7d3e0a1
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 39 deletions.
43 changes: 23 additions & 20 deletions zellij-server/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub(crate) struct Screen {
position_and_size: PositionAndSize,
/// The index of this [`Screen`]'s active [`Tab`].
active_tab_index: Option<usize>,
previous_active_tab_index: Option<usize>,
tab_history: Vec<Option<usize>>,
mode_info: ModeInfo,
colors: Palette,
session_state: Arc<RwLock<SessionState>>,
Expand All @@ -171,8 +171,8 @@ impl Screen {
position_and_size: client_attributes.position_and_size,
colors: client_attributes.palette,
active_tab_index: None,
previous_active_tab_index: None,
tabs: BTreeMap::new(),
tab_history: Vec::with_capacity(32),
mode_info,
session_state,
}
Expand All @@ -196,7 +196,7 @@ impl Screen {
self.colors,
self.session_state.clone(),
);
self.previous_active_tab_index = self.active_tab_index;
self.tab_history.push(self.active_tab_index);
self.active_tab_index = Some(tab_index);
self.tabs.insert(tab_index, tab);
self.update_tabs();
Expand All @@ -222,7 +222,8 @@ impl Screen {
for tab in self.tabs.values_mut() {
if tab.position == new_tab_pos {
tab.set_force_render();
self.previous_active_tab_index = self.active_tab_index;
self.tab_history.retain(|&e| e != Some(tab.index));
self.tab_history.push(self.active_tab_index);
self.active_tab_index = Some(tab.index);
break;
}
Expand All @@ -242,7 +243,8 @@ impl Screen {
for tab in self.tabs.values_mut() {
if tab.position == new_tab_pos {
tab.set_force_render();
self.previous_active_tab_index = self.active_tab_index;
self.tab_history.retain(|&e| e != Some(tab.index));
self.tab_history.push(self.active_tab_index);
self.active_tab_index = Some(tab.index);
break;
}
Expand All @@ -257,7 +259,8 @@ impl Screen {
if let Some(t) = self.tabs.values_mut().find(|t| t.position == tab_index) {
if t.index != active_tab_index {
t.set_force_render();
self.previous_active_tab_index = self.active_tab_index;
self.tab_history.retain(|&e| e != Some(t.index));
self.tab_history.push(self.active_tab_index);
self.active_tab_index = Some(t.index);
self.update_tabs();
self.render();
Expand All @@ -268,11 +271,7 @@ impl Screen {
/// Closes this [`Screen`]'s active [`Tab`], exiting the application if it happens
/// to be the last tab.
pub fn close_tab(&mut self) {
let future_previous = self.previous_active_tab_index;
let active_tab_index = self.active_tab_index.unwrap();
if self.tabs.len() > 1 {
self.switch_tab_prev();
}
let active_tab = self.tabs.remove(&active_tab_index).unwrap();
let pane_ids = active_tab.get_pane_ids();
// below we don't check the result of sending the CloseTab instruction to the pty thread
Expand All @@ -284,22 +283,21 @@ impl Screen {
.unwrap();
if self.tabs.is_empty() {
self.active_tab_index = None;
self.previous_active_tab_index = None;
if *self.session_state.read().unwrap() == SessionState::Attached {
self.bus
.senders
.send_to_server(ServerInstruction::Render(None))
.unwrap();
}
} else {
self.active_tab_index = self.tab_history.pop().unwrap();
for t in self.tabs.values_mut() {
if t.position > active_tab.position {
t.position -= 1;
}
}
self.update_tabs();
}
self.previous_active_tab_index = future_previous;
}

pub fn resize_to_screen(&mut self, new_screen_size: PositionAndSize) {
Expand Down Expand Up @@ -339,8 +337,13 @@ impl Screen {
}

/// Returns an immutable reference to this [`Screen`]'s previous active [`Tab`].
pub fn get_previous_tab(&self) -> Option<&Tab> {
match self.previous_active_tab_index {
/// Consumes the last entry in tab history.
pub fn get_previous_tab(&mut self) -> Option<&Tab> {
let last = self.tab_history.pop();
if last.is_none() {
return None;
}
match last.unwrap() {
Some(tab) => self.tabs.get(&tab),
None => None,
}
Expand Down Expand Up @@ -373,7 +376,7 @@ impl Screen {
self.session_state.clone(),
);
tab.apply_layout(layout, new_pids);
self.previous_active_tab_index = self.active_tab_index;
self.tab_history.push(self.active_tab_index);
self.active_tab_index = Some(tab_index);
self.tabs.insert(tab_index, tab);
self.update_tabs();
Expand Down Expand Up @@ -431,12 +434,12 @@ impl Screen {
}
}
pub fn toggle_tab(&mut self) {
let active_tab_index = self.active_tab_index.unwrap();
if self.previous_active_tab_index.is_some() {
let position = self.get_previous_tab().unwrap().position;
let tab = self.get_previous_tab();
if let Some(t) = tab {
let position = t.position;
self.go_to_tab(position + 1);
}
self.previous_active_tab_index = Some(active_tab_index);
};

self.update_tabs();
self.render();
}
Expand Down
96 changes: 77 additions & 19 deletions zellij-server/src/unit/screen_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ pub fn close_the_middle_tab() {
assert_eq!(screen.tabs.len(), 2, "Two tabs left");
assert_eq!(
screen.get_active_tab().unwrap().position,
0,
1,
"Active tab switched to previous tab"
);
}
Expand Down Expand Up @@ -294,19 +294,35 @@ pub fn toggle_to_previous_tab_create_tabs_only() {
screen.new_tab(2);
screen.new_tab(3);

assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(1)],
"Tab history is invalid"
);

screen.toggle_tab();
assert_eq!(
screen.get_active_tab().unwrap().position,
1,
"Active tab toggler to previous tab"
);
assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(2)],
"Tab history is invalid"
);

screen.toggle_tab();
assert_eq!(
screen.get_active_tab().unwrap().position,
2,
"Active tab toggler to previous tab"
);
assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(1)],
"Tab history is invalid"
);

screen.toggle_tab();
assert_eq!(
Expand All @@ -327,48 +343,90 @@ pub fn toggle_to_previous_tab_delete() {
};
let mut screen = create_new_screen(position_and_size);

screen.new_tab(1);
screen.new_tab(2);
screen.new_tab(3);
screen.new_tab(1); // 0
screen.new_tab(2); // 1
screen.new_tab(3); // 2
screen.new_tab(4); // 3

screen.toggle_tab();
assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(1), Some(2)],
"Tab history is invalid"
);
assert_eq!(
screen.get_active_tab().unwrap().position,
1,
3,
"Active tab toggler to previous tab"
);

screen.toggle_tab();
assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(1), Some(3)],
"Tab history is invalid"
);
assert_eq!(
screen.get_previous_tab().unwrap().position,
screen.get_active_tab().unwrap().position,
2,
"Previous active tab invalid"
"Active tab toggler to previous tab"
);

screen.close_tab();
screen.toggle_tab();
assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(1), Some(2)],
"Tab history is invalid"
);
assert_eq!(
screen.get_active_tab().unwrap().position,
0,
3,
"Active tab toggler to previous tab"
);

screen.switch_tab_prev();
assert_eq!(
screen.get_previous_tab().unwrap().position,
1,
"Previous active tab invalid"
screen.tab_history,
vec![None, Some(0), Some(1), Some(3)],
"Tab history is invalid"
);
assert_eq!(
screen.get_previous_tab().unwrap().index,
screen.get_active_tab().unwrap().position,
2,
"Previous active tab invalid"
"Active tab toggler to previous tab"
);
screen.switch_tab_prev();
assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(3), Some(2)],
"Tab history is invalid"
);
assert_eq!(
screen.get_active_tab().unwrap().position,
1,
"Active tab toggler to previous tab"
);

screen.toggle_tab();
screen.close_tab();
assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(3)],
"Tab history is invalid"
);
assert_eq!(
screen.get_active_tab().unwrap().position,
1,
"Active tab toggler to previous tab"
);

screen.toggle_tab();
assert_eq!(
screen.get_previous_tab().unwrap().position,
0,
"Previous active tab invalid"
screen.get_active_tab().unwrap().position,
2,
"Active tab toggler to previous tab"
);
assert_eq!(
screen.tab_history,
vec![None, Some(0), Some(2)],
"Tab history is invalid"
);
}

0 comments on commit 7d3e0a1

Please sign in to comment.