diff --git a/mux/src/pane.rs b/mux/src/pane.rs index 979c502b8..5a284d527 100644 --- a/mux/src/pane.rs +++ b/mux/src/pane.rs @@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize}; use std::cell::RefMut; use std::ops::Range; use std::sync::{Arc, Mutex}; +use termwiz::hyperlink::Rule; use termwiz::surface::Line; use url::Url; use wezterm_term::color::ColorPalette; @@ -95,6 +96,23 @@ impl LogicalLine { self.logical.cells().len() ); } + + pub fn apply_hyperlink_rules(&mut self, rules: &[Rule]) { + self.logical.invalidate_implicit_hyperlinks(); + self.logical.scan_and_create_hyperlinks(rules); + if !self.logical.has_hyperlink() { + return; + } + + // Re-compute the physical lines + let mut line = self.logical.clone(); + let num_phys = self.physical_lines.len(); + for (idx, phys) in self.physical_lines.iter_mut().enumerate() { + let len = phys.cells().len(); + *phys = line.split_off(len); + phys.set_last_cell_was_wrapped(idx == num_phys - 1); + } + } } /// A Pane represents a view on a terminal @@ -190,6 +208,31 @@ pub trait Pane: Downcast { lines } + fn get_lines_with_hyperlinks_applied( + &self, + lines: Range, + rules: &[Rule], + ) -> (StableRowIndex, Vec) { + let requested_first = lines.start; + let logical = self.get_logical_lines(lines); + + let mut first = None; + let mut phys_lines = vec![]; + for mut log_line in logical { + log_line.apply_hyperlink_rules(rules); + for (idx, phys) in log_line.physical_lines.into_iter().enumerate() { + if log_line.first_row + idx as StableRowIndex >= requested_first { + if first.is_none() { + first.replace(log_line.first_row + idx as StableRowIndex); + } + phys_lines.push(phys); + } + } + } + + (first.unwrap(), phys_lines) + } + /// Returns render related dimensions fn get_dimensions(&self) -> RenderableDimensions; diff --git a/mux/src/renderable.rs b/mux/src/renderable.rs index 2baf67373..3f2754340 100644 --- a/mux/src/renderable.rs +++ b/mux/src/renderable.rs @@ -1,4 +1,3 @@ -use config::configuration; use luahelper::impl_lua_conversion; use rangeset::RangeSet; use serde::{Deserialize, Serialize}; @@ -77,7 +76,6 @@ pub fn terminal_get_lines( ) -> (StableRowIndex, Vec) { 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 @@ -86,7 +84,6 @@ pub fn terminal_get_lines( .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 diff --git a/termwiz/src/surface/line.rs b/termwiz/src/surface/line.rs index 5e2544332..57e01a56d 100644 --- a/termwiz/src/surface/line.rs +++ b/termwiz/src/surface/line.rs @@ -235,6 +235,14 @@ impl Line { s } + pub fn split_off(&mut self, idx: usize) -> Self { + let cells = self.cells.split_off(idx); + Self { + bits: self.bits, + cells, + } + } + pub fn compute_double_click_range bool>( &self, click_col: usize, diff --git a/wezterm-gui/src/termwindow/render.rs b/wezterm-gui/src/termwindow/render.rs index ba10508a8..adaa70c49 100644 --- a/wezterm-gui/src/termwindow/render.rs +++ b/wezterm-gui/src/termwindow/render.rs @@ -172,7 +172,9 @@ impl super::TermWindow { None => dims.physical_top..dims.physical_top + dims.viewport_rows as StableRowIndex, }; - let (top, vp_lines) = pos.pane.get_lines(stable_range); + let (top, vp_lines) = pos + .pane + .get_lines_with_hyperlinks_applied(stable_range, &self.config.hyperlink_rules); stable_top = top; lines = vp_lines; }