Skip to content

Commit

Permalink
mux/wezterm: move Renderable into Pane
Browse files Browse the repository at this point in the history
This makes it easier to overrride/overlay inside the mux when
indicating that we are in tmux mode.

refs: #336
  • Loading branch information
wez committed Nov 20, 2020
1 parent fffb9b3 commit 91f1cc2
Show file tree
Hide file tree
Showing 16 changed files with 357 additions and 363 deletions.
49 changes: 38 additions & 11 deletions mux/src/localpane.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use crate::domain::DomainId;
use crate::pane::{Pane, PaneId, Pattern, SearchResult};
use crate::renderable::Renderable;
use crate::renderable::*;
use crate::tmux::{TmuxDomain, TmuxDomainState};
use crate::{Domain, Mux};
use anyhow::Error;
use async_trait::async_trait;
use portable_pty::{Child, MasterPty, PtySize};
use rangeset::RangeSet;
use std::cell::{RefCell, RefMut};
use std::ops::Range;
use std::sync::Arc;
use termwiz::escape::DeviceControlMode;
use termwiz::surface::Line;
use url::Url;
use wezterm_term::color::ColorPalette;
use wezterm_term::{
Clipboard, KeyCode, KeyModifiers, MouseEvent, SemanticZone, StableRowIndex, Terminal,
CellAttributes, Clipboard, KeyCode, KeyModifiers, MouseEvent, SemanticZone, StableRowIndex,
Terminal,
};

pub struct LocalPane {
Expand All @@ -30,17 +34,40 @@ impl Pane for LocalPane {
self.pane_id
}

fn renderer(&self) -> RefMut<dyn Renderable> {
/*
{
let tmux_domain = self.tmux_domain.borrow();
let mut tmux = tmux_domain.as_ref().cloned();
if let Some(tmux) = tmux.take() {
return RefMut::map(tmux.renderable.borrow_mut(), |r| &mut *r);
fn get_cursor_position(&self) -> StableCursorPosition {
let mut cursor = terminal_get_cursor_position(&mut self.terminal.borrow_mut());
if self.tmux_domain.borrow().is_some() {
cursor.visibility = termwiz::surface::CursorVisibility::Hidden;
}
cursor
}

fn get_dirty_lines(&self, lines: Range<StableRowIndex>) -> RangeSet<StableRowIndex> {
terminal_get_dirty_lines(&mut self.terminal.borrow_mut(), lines)
}

fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
let (first, mut lines) = terminal_get_lines(&mut self.terminal.borrow_mut(), lines);

if self.tmux_domain.borrow().is_some() {
let cursor = terminal_get_cursor_position(&mut self.terminal.borrow_mut());
let idx = cursor.y as isize - first as isize;
if idx > 0 {
if let Some(line) = lines.get_mut(idx as usize) {
line.overlay_text_with_attribute(
0,
"This pane is running tmux control mode",
CellAttributes::default(),
);
}
}
}
*/
RefMut::map(self.terminal.borrow_mut(), |t| &mut *t)

(first, lines)
}

fn get_dimensions(&self) -> RenderableDimensions {
terminal_get_dimensions(&mut self.terminal.borrow_mut())
}

fn kill(&self) {
Expand Down
35 changes: 33 additions & 2 deletions mux/src/pane.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::domain::DomainId;
use crate::renderable::Renderable;
use crate::renderable::*;
use crate::Mux;
use async_trait::async_trait;
use downcast_rs::{impl_downcast, Downcast};
use portable_pty::PtySize;
use rangeset::RangeSet;
use serde::{Deserialize, Serialize};
use std::cell::RefMut;
use std::ops::Range;
use std::sync::{Arc, Mutex};
use termwiz::surface::Line;
use url::Url;
use wezterm_term::color::ColorPalette;
use wezterm_term::{Clipboard, KeyCode, KeyModifiers, MouseEvent, SemanticZone, StableRowIndex};
Expand Down Expand Up @@ -69,7 +72,35 @@ fn schedule_next_paste(paste: &Arc<Mutex<Paste>>) {
#[async_trait(?Send)]
pub trait Pane: Downcast {
fn pane_id(&self) -> PaneId;
fn renderer(&self) -> RefMut<dyn Renderable>;

/// Returns the 0-based cursor position relative to the top left of
/// the visible screen
fn get_cursor_position(&self) -> StableCursorPosition;

/// Given a range of lines, return the subset of those lines that
/// have their dirty flag set to true.
fn get_dirty_lines(&self, lines: Range<StableRowIndex>) -> RangeSet<StableRowIndex>;

/// Returns a set of lines from the scrollback or visible portion of
/// the display. The lines are indexed using StableRowIndex, which
/// can be invalidated if the scrollback is busy, or when switching
/// to the alternate screen.
/// To deal with this, this function will adjust the input so that
/// a range that has been scrolled off the top will return the top
/// n rows of the scrollback (where n is the size of the input range),
/// or the bottom n rows of the scrollback when switching to the alt
/// screen and the index would go off the bottom.
/// Because of this, we also return the adjusted StableRowIndex for
/// the first row in the range.
///
/// For each line, if it was dirty in the backing data, then the dirty
/// flag will be cleared in the backing data. The returned line will
/// have its dirty bit set appropriately.
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>);

/// Returns render related dimensions
fn get_dimensions(&self) -> RenderableDimensions;

fn get_title(&self) -> String;
fn send_paste(&self, text: &str) -> anyhow::Result<()>;
fn reader(&self) -> anyhow::Result<Box<dyn std::io::Read + Send>>;
Expand Down
147 changes: 60 additions & 87 deletions mux/src/renderable.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use config::configuration;
use downcast_rs::{impl_downcast, Downcast};
use luahelper::impl_lua_conversion;
use rangeset::RangeSet;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -37,99 +36,73 @@ pub struct RenderableDimensions {
}
impl_lua_conversion!(RenderableDimensions);

/// Renderable allows passing something that isn't an actual wezterm_term::Terminal
/// instance into the renderer, which opens up remoting of the terminal
/// surfaces via a multiplexer.
pub trait Renderable: Downcast {
/// Returns the 0-based cursor position relative to the top left of
/// the visible screen
fn get_cursor_position(&self) -> StableCursorPosition;
/// Implements Pane::get_cursor_position for Terminal
pub fn terminal_get_cursor_position(term: &mut Terminal) -> StableCursorPosition {
let pos = term.cursor_pos();

/// Given a range of lines, return the subset of those lines that
/// have their dirty flag set to true.
fn get_dirty_lines(&self, lines: Range<StableRowIndex>) -> RangeSet<StableRowIndex>;

/// Returns a set of lines from the scrollback or visible portion of
/// the display. The lines are indexed using StableRowIndex, which
/// can be invalidated if the scrollback is busy, or when switching
/// to the alternate screen.
/// To deal with this, this function will adjust the input so that
/// a range that has been scrolled off the top will return the top
/// n rows of the scrollback (where n is the size of the input range),
/// or the bottom n rows of the scrollback when switching to the alt
/// screen and the index would go off the bottom.
/// Because of this, we also return the adjusted StableRowIndex for
/// the first row in the range.
///
/// For each line, if it was dirty in the backing data, then the dirty
/// flag will be cleared in the backing data. The returned line will
/// have its dirty bit set appropriately.
fn get_lines(&mut self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>);

/// Returns render related dimensions
fn get_dimensions(&self) -> RenderableDimensions;
StableCursorPosition {
x: pos.x,
y: term.screen().visible_row_to_stable_row(pos.y),
shape: pos.shape,
visibility: pos.visibility,
}
}
impl_downcast!(Renderable);

impl Renderable for Terminal {
fn get_cursor_position(&self) -> StableCursorPosition {
let pos = self.cursor_pos();

StableCursorPosition {
x: pos.x,
y: self.screen().visible_row_to_stable_row(pos.y),
shape: pos.shape,
visibility: pos.visibility,
/// Implements Pane::get_dirty_lines for Terminal
pub fn terminal_get_dirty_lines(
term: &mut Terminal,
lines: Range<StableRowIndex>,
) -> RangeSet<StableRowIndex> {
let screen = term.screen();
let phys = screen.stable_range(&lines);
let mut set = RangeSet::new();
for (idx, line) in screen
.lines
.iter()
.enumerate()
.skip(phys.start)
.take(phys.end - phys.start)
{
if line.is_dirty() {
set.add(screen.phys_to_stable_row_index(idx))
}
}
set
}

fn get_dirty_lines(&self, lines: Range<StableRowIndex>) -> RangeSet<StableRowIndex> {
let screen = self.screen();
let phys = screen.stable_range(&lines);
let mut set = RangeSet::new();
for (idx, line) in screen
/// Implements Pane::get_lines for Terminal
pub fn terminal_get_lines(
term: &mut Terminal,
lines: Range<StableRowIndex>,
) -> (StableRowIndex, Vec<Line>) {
let screen = term.screen_mut();
let phys_range = screen.stable_range(&lines);
let config = configuration();
(
screen.phys_to_stable_row_index(phys_range.start),
screen
.lines
.iter()
.enumerate()
.skip(phys.start)
.take(phys.end - phys.start)
{
if line.is_dirty() {
set.add(screen.phys_to_stable_row_index(idx))
}
}
set
}

fn get_lines(&mut self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
let screen = self.screen_mut();
let phys_range = screen.stable_range(&lines);
let config = configuration();
(
screen.phys_to_stable_row_index(phys_range.start),
screen
.lines
.iter_mut()
.skip(phys_range.start)
.take(phys_range.end - phys_range.start)
.map(|line| {
line.scan_and_create_hyperlinks(&config.hyperlink_rules);
let cloned = line.clone();
line.clear_dirty();
cloned
})
.collect(),
)
}
.iter_mut()
.skip(phys_range.start)
.take(phys_range.end - phys_range.start)
.map(|line| {
line.scan_and_create_hyperlinks(&config.hyperlink_rules);
let cloned = line.clone();
line.clear_dirty();
cloned
})
.collect(),
)
}

fn get_dimensions(&self) -> RenderableDimensions {
let screen = self.screen();
RenderableDimensions {
cols: screen.physical_cols,
viewport_rows: screen.physical_rows,
scrollback_rows: screen.lines.len(),
physical_top: screen.visible_row_to_stable_row(0),
scrollback_top: screen.phys_to_stable_row_index(0),
}
/// Implements Pane::get_dimensions for Terminal
pub fn terminal_get_dimensions(term: &mut Terminal) -> RenderableDimensions {
let screen = term.screen();
RenderableDimensions {
cols: screen.physical_cols,
viewport_rows: screen.physical_rows,
scrollback_rows: screen.lines.len(),
physical_top: screen.visible_row_to_stable_row(0),
scrollback_top: screen.phys_to_stable_row_index(0),
}
}
28 changes: 22 additions & 6 deletions mux/src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ fn pane_tree(
node: data.unwrap(),
},
Tree::Leaf(pane) => {
let dims = pane.renderer().get_dimensions();
let dims = pane.get_dimensions();
let working_dir = pane.get_current_working_dir();

PaneNode::Leaf(PaneEntry {
Expand Down Expand Up @@ -789,7 +789,7 @@ impl Tab {
match node {
Tree::Empty => None,
Tree::Leaf(pane) => {
let dims = pane.renderer().get_dimensions();
let dims = pane.get_dimensions();
let size = PtySize {
cols: dims.cols as u16,
rows: dims.viewport_rows as u16,
Expand Down Expand Up @@ -1480,10 +1480,12 @@ impl Into<String> for SerdeUrl {
#[cfg(test)]
mod test {
use super::*;
use crate::renderable::Renderable;
use crate::renderable::*;
use rangeset::RangeSet;
use std::ops::Range;
use url::Url;
use wezterm_term::color::ColorPalette;
use wezterm_term::{KeyCode, KeyModifiers, MouseEvent};
use wezterm_term::{KeyCode, KeyModifiers, Line, MouseEvent, StableRowIndex};

struct FakePane {
id: PaneId,
Expand All @@ -1503,9 +1505,23 @@ mod test {
fn pane_id(&self) -> PaneId {
self.id
}
fn renderer(&self) -> RefMut<dyn Renderable> {
unimplemented!()

fn get_cursor_position(&self) -> StableCursorPosition {
unimplemented!();
}

fn get_dirty_lines(&self, _lines: Range<StableRowIndex>) -> RangeSet<StableRowIndex> {
unimplemented!();
}

fn get_lines(&self, _lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
unimplemented!();
}

fn get_dimensions(&self) -> RenderableDimensions {
unimplemented!();
}

fn get_title(&self) -> String {
unimplemented!()
}
Expand Down
Loading

0 comments on commit 91f1cc2

Please sign in to comment.