Skip to content

Commit

Permalink
Feature: Add pane names (#928)
Browse files Browse the repository at this point in the history
* Read pane name from layout

* Update pane name at runtime

* Fix tests

* prefer and render pane name over pane title

* fix clippy errors

* fix after rebase
  • Loading branch information
kunalmohan authored Dec 9, 2021
1 parent 368c852 commit c75bcbd
Show file tree
Hide file tree
Showing 21 changed files with 233 additions and 22 deletions.
2 changes: 1 addition & 1 deletion default-plugins/status-bar/src/first_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ pub fn ctrl_keys(help: &ModeInfo, max_len: usize, separator: &str) -> LinePart {
colored_elements,
separator,
),
InputMode::Pane => key_indicators(
InputMode::Pane | InputMode::RenamePane => key_indicators(
max_len,
&[
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Lock),
Expand Down
3 changes: 2 additions & 1 deletion src/tests/e2e/remote_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ fn read_from_channel(
let last_snapshot = last_snapshot.clone();
let cursor_coordinates = cursor_coordinates.clone();
let mut vte_parser = vte::Parser::new();
let mut terminal_output = TerminalPane::new(0, *pane_geom, Palette::default(), 0); // 0 is the pane index
let mut terminal_output =
TerminalPane::new(0, *pane_geom, Palette::default(), 0, String::new()); // 0 is the pane index
let mut retries_left = 3;
move || {
let mut should_sleep = false;
Expand Down
2 changes: 1 addition & 1 deletion zellij-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub fn start_client(
client_attributes,
Box::new(opts),
Box::new(config_options.clone()),
layout.unwrap(),
Box::new(layout.unwrap()),
Some(config.plugins.clone()),
)
}
Expand Down
4 changes: 2 additions & 2 deletions zellij-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub enum ServerInstruction {
ClientAttributes,
Box<CliArgs>,
Box<Options>,
LayoutFromYaml,
Box<LayoutFromYaml>,
ClientId,
Option<PluginsConfig>,
),
Expand Down Expand Up @@ -531,7 +531,7 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
pub struct SessionOptions {
pub opts: Box<CliArgs>,
pub config_options: Box<Options>,
pub layout: LayoutFromYaml,
pub layout: Box<LayoutFromYaml>,
pub plugins: Option<PluginsConfig>,
}

Expand Down
38 changes: 35 additions & 3 deletions zellij-server/src/panes/plugin_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::ClientId;
use zellij_utils::pane_size::Offset;
use zellij_utils::position::Position;
use zellij_utils::shared::ansi_len;
use zellij_utils::zellij_tile::prelude::{Event, Mouse, PaletteColor};
use zellij_utils::zellij_tile::prelude::{Event, InputMode, Mouse, PaletteColor};
use zellij_utils::{
channels::SenderWithContext,
pane_size::{Dimension, PaneGeom},
Expand All @@ -28,6 +28,7 @@ pub(crate) struct PluginPane {
pub send_plugin_instructions: SenderWithContext<PluginInstruction>,
pub active_at: Instant,
pub pane_title: String,
pub pane_name: String,
frame: bool,
borderless: bool,
}
Expand All @@ -38,6 +39,7 @@ impl PluginPane {
position_and_size: PaneGeom,
send_plugin_instructions: SenderWithContext<PluginInstruction>,
title: String,
pane_name: String,
) -> Self {
Self {
pid,
Expand All @@ -51,6 +53,7 @@ impl PluginPane {
content_offset: Offset::default(),
pane_title: title,
borderless: false,
pane_name,
}
}
}
Expand Down Expand Up @@ -209,14 +212,29 @@ impl Pane for PluginPane {
None
}
}
fn render_frame(&mut self, _client_id: ClientId, frame_params: FrameParams) -> Option<String> {
fn render_frame(
&mut self,
_client_id: ClientId,
frame_params: FrameParams,
input_mode: InputMode,
) -> Option<String> {
// FIXME: This is a hack that assumes all fixed-size panes are borderless. This
// will eventually need fixing!
if self.frame && !(self.geom.rows.is_fixed() || self.geom.cols.is_fixed()) {
let pane_title = if self.pane_name.is_empty()
&& input_mode == InputMode::RenamePane
&& frame_params.is_main_client
{
String::from("Enter name...")
} else if self.pane_name.is_empty() {
self.pane_title.clone()
} else {
self.pane_name.clone()
};
let frame = PaneFrame::new(
self.current_geom().into(),
(0, 0), // scroll position
self.pane_title.clone(),
pane_title,
frame_params,
);
Some(frame.render())
Expand All @@ -231,6 +249,20 @@ impl Pane for PluginPane {
) -> Option<String> {
None
}
fn update_name(&mut self, name: &str) {
match name {
"\0" => {
self.pane_name = String::new();
}
"\u{007F}" | "\u{0008}" => {
//delete and backspace keys
self.pane_name.pop();
}
c => {
self.pane_name.push_str(c);
}
}
}
fn pid(&self) -> PaneId {
PaneId::Plugin(self.pid)
}
Expand Down
44 changes: 38 additions & 6 deletions zellij-server/src/panes/terminal_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use zellij_utils::{
pane_size::{Dimension, PaneGeom},
position::Position,
vte,
zellij_tile::data::{Palette, PaletteColor},
zellij_tile::data::{InputMode, Palette, PaletteColor},
};

pub const SELECTION_SCROLL_INTERVAL_MS: u64 = 10;
Expand All @@ -44,6 +44,7 @@ pub struct TerminalPane {
selection_scrolled_at: time::Instant,
content_offset: Offset,
pane_title: String,
pane_name: String,
frame: HashMap<ClientId, PaneFrame>,
borderless: bool,
fake_cursor_locations: HashSet<(usize, usize)>, // (x, y) - these hold a record of previous fake cursors which we need to clear on render
Expand Down Expand Up @@ -278,16 +279,31 @@ impl Pane for TerminalPane {
None
}
}
fn render_frame(&mut self, client_id: ClientId, frame_params: FrameParams) -> Option<String> {
fn render_frame(
&mut self,
client_id: ClientId,
frame_params: FrameParams,
input_mode: InputMode,
) -> Option<String> {
// TODO: remove the cursor stuff from here
let mut vte_output = None;
let frame = PaneFrame::new(
self.current_geom().into(),
self.grid.scrollback_position_and_length(),
let pane_title = if self.pane_name.is_empty()
&& input_mode == InputMode::RenamePane
&& frame_params.is_main_client
{
String::from("Enter name...")
} else if self.pane_name.is_empty() {
self.grid
.title
.clone()
.unwrap_or_else(|| self.pane_title.clone()),
.unwrap_or_else(|| self.pane_title.clone())
} else {
self.pane_name.clone()
};
let frame = PaneFrame::new(
self.current_geom().into(),
self.grid.scrollback_position_and_length(),
pane_title,
frame_params,
);
match self.frame.get(&client_id) {
Expand Down Expand Up @@ -336,6 +352,20 @@ impl Pane for TerminalPane {
}
vte_output
}
fn update_name(&mut self, name: &str) {
match name {
"\0" => {
self.pane_name = String::new();
}
"\u{007F}" | "\u{0008}" => {
//delete and backspace keys
self.pane_name.pop();
}
c => {
self.pane_name.push_str(c);
}
}
}
fn pid(&self) -> PaneId {
PaneId::Terminal(self.pid)
}
Expand Down Expand Up @@ -475,6 +505,7 @@ impl TerminalPane {
position_and_size: PaneGeom,
palette: Palette,
pane_index: usize,
pane_name: String,
) -> TerminalPane {
let initial_pane_title = format!("Pane #{}", pane_index);
let grid = Grid::new(
Expand All @@ -495,6 +526,7 @@ impl TerminalPane {
colors: palette,
selection_scrolled_at: time::Instant::now(),
pane_title: initial_pane_title,
pane_name,
borderless: false,
fake_cursor_locations: HashSet::new(),
}
Expand Down
2 changes: 1 addition & 1 deletion zellij-server/src/panes/unit/terminal_pane_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub fn scrolling_inside_a_pane() {

let pid = 1;
let palette = Palette::default();
let mut terminal_pane = TerminalPane::new(pid, fake_win_size, palette, 0); // 0 is the pane index
let mut terminal_pane = TerminalPane::new(pid, fake_win_size, palette, 0, String::new()); // 0 is the pane index
let mut text_to_fill_pane = String::new();
for i in 0..30 {
writeln!(&mut text_to_fill_pane, "\rline {}", i + 1).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion zellij-server/src/pty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub(crate) struct Pty {

use std::convert::TryFrom;

pub(crate) fn pty_thread_main(mut pty: Pty, layout: LayoutFromYaml) {
pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<LayoutFromYaml>) {
loop {
let (event, mut err_ctx) = pty.bus.recv().expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Pty((&event).into()));
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 @@ -226,6 +226,12 @@ fn route_action(
};
session.senders.send_to_pty(pty_instr).unwrap();
}
Action::PaneNameInput(c) => {
session
.senders
.send_to_screen(ScreenInstruction::UpdatePaneName(c, client_id))
.unwrap();
}
Action::Run(command) => {
let run_cmd = Some(TerminalAction::RunCommand(command.clone().into()));
let pty_instr = match command.direction {
Expand Down
10 changes: 10 additions & 0 deletions zellij-server/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub enum ScreenInstruction {
TogglePaneFrames,
SetSelectable(PaneId, bool, usize),
ClosePane(PaneId, Option<ClientId>),
UpdatePaneName(Vec<u8>, ClientId),
NewTab(Layout, Vec<RawFd>, ClientId),
SwitchTabNext(ClientId),
SwitchTabPrev(ClientId),
Expand Down Expand Up @@ -140,6 +141,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::TogglePaneFrames => ScreenContext::TogglePaneFrames,
ScreenInstruction::SetSelectable(..) => ScreenContext::SetSelectable,
ScreenInstruction::ClosePane(..) => ScreenContext::ClosePane,
ScreenInstruction::UpdatePaneName(..) => ScreenContext::UpdatePaneName,
ScreenInstruction::NewTab(..) => ScreenContext::NewTab,
ScreenInstruction::SwitchTabNext(..) => ScreenContext::SwitchTabNext,
ScreenInstruction::SwitchTabPrev(..) => ScreenContext::SwitchTabPrev,
Expand Down Expand Up @@ -975,6 +977,14 @@ pub(crate) fn screen_thread_main(
}
screen.update_tabs();
}
ScreenInstruction::UpdatePaneName(c, client_id) => {
screen
.get_active_tab_mut(client_id)
.unwrap()
.update_active_pane_name(c, client_id);

screen.render();
}
ScreenInstruction::ToggleActiveTerminalFullscreen(client_id) => {
screen
.get_active_tab_mut(client_id)
Expand Down
36 changes: 32 additions & 4 deletions zellij-server/src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ use std::time::Instant;
use std::{
cmp::Reverse,
collections::{BTreeMap, HashMap, HashSet},
str,
};
use zellij_tile::data::{Event, ModeInfo, Palette, PaletteColor};
use zellij_tile::data::{Event, InputMode, ModeInfo, Palette, PaletteColor};
use zellij_utils::{
input::{
layout::{Direction, Layout, Run},
Expand Down Expand Up @@ -181,12 +182,18 @@ pub trait Pane {
fn selectable(&self) -> bool;
fn set_selectable(&mut self, selectable: bool);
fn render(&mut self, client_id: Option<ClientId>) -> Option<String>;
fn render_frame(&mut self, client_id: ClientId, frame_params: FrameParams) -> Option<String>;
fn render_frame(
&mut self,
client_id: ClientId,
frame_params: FrameParams,
input_mode: InputMode,
) -> Option<String>;
fn render_fake_cursor(
&mut self,
cursor_color: PaletteColor,
text_color: PaletteColor,
) -> Option<String>;
fn update_name(&mut self, name: &str);
fn pid(&self) -> PaneId;
fn reduce_height(&mut self, percent: f64);
fn increase_height(&mut self, percent: f64);
Expand Down Expand Up @@ -400,6 +407,7 @@ impl Tab {
*position_and_size,
self.senders.to_plugin.as_ref().unwrap().clone(),
pane_title,
layout.pane_name.clone().unwrap_or_default(),
);
new_plugin.set_borderless(layout.borderless);
self.panes.insert(PaneId::Plugin(pid), Box::new(new_plugin));
Expand All @@ -412,6 +420,7 @@ impl Tab {
*position_and_size,
self.colors,
next_terminal_position,
layout.pane_name.clone().unwrap_or_default(),
);
new_pane.set_borderless(layout.borderless);
self.panes
Expand Down Expand Up @@ -588,6 +597,7 @@ impl Tab {
bottom_winsize,
self.colors,
next_terminal_position,
String::new(),
);
terminal_to_split.set_geom(top_winsize);
self.panes.insert(pid, Box::new(new_terminal));
Expand All @@ -604,6 +614,7 @@ impl Tab {
right_winsize,
self.colors,
next_terminal_position,
String::new(),
);
terminal_to_split.set_geom(left_winsize);
self.panes.insert(pid, Box::new(new_terminal));
Expand Down Expand Up @@ -647,6 +658,7 @@ impl Tab {
bottom_winsize,
self.colors,
next_terminal_position,
String::new(),
);
active_pane.set_geom(top_winsize);
self.panes.insert(pid, Box::new(new_terminal));
Expand Down Expand Up @@ -684,8 +696,13 @@ impl Tab {
}
let terminal_ws = active_pane.position_and_size();
if let Some((left_winsize, right_winsize)) = split(Direction::Vertical, &terminal_ws) {
let new_terminal =
TerminalPane::new(term_pid, right_winsize, self.colors, next_terminal_position);
let new_terminal = TerminalPane::new(
term_pid,
right_winsize,
self.colors,
next_terminal_position,
String::new(),
);
active_pane.set_geom(left_winsize);
self.panes.insert(pid, Box::new(new_terminal));
}
Expand Down Expand Up @@ -3451,6 +3468,17 @@ impl Tab {
.unwrap();
}
}

pub fn update_active_pane_name(&mut self, buf: Vec<u8>, client_id: ClientId) {
if let Some(active_terminal_id) = self.get_active_terminal_id(client_id) {
let s = str::from_utf8(&buf).unwrap();
let active_terminal = self
.panes
.get_mut(&PaneId::Terminal(active_terminal_id))
.unwrap();
active_terminal.update_name(s);
}
}
}

#[allow(clippy::borrowed_box)]
Expand Down
2 changes: 1 addition & 1 deletion zellij-server/src/ui/pane_contents_and_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl<'a> PaneContentsAndUi<'a> {
other_cursors_exist_in_session: self.multiple_users_exist_in_session,
}
};
if let Some(vte_output) = self.pane.render_frame(client_id, frame_params) {
if let Some(vte_output) = self.pane.render_frame(client_id, frame_params, client_mode) {
// FIXME: Use Termion for cursor and style clearing?
self.output.push_to_client(
client_id,
Expand Down
Loading

0 comments on commit c75bcbd

Please sign in to comment.