added the fields for drawing the hyperlinks

Mikayla Maki created

Change summary

crates/terminal/src/terminal.rs         | 20 ++++++------
crates/terminal/src/terminal_element.rs | 39 ++++++++++++++++++++++++--
2 files changed, 45 insertions(+), 14 deletions(-)

Detailed changes

crates/terminal/src/terminal.rs 🔗

@@ -387,7 +387,6 @@ impl TerminalBuilder {
             foreground_process_info: None,
             breadcrumb_text: String::new(),
             scroll_px: 0.,
-            last_hovered_hyperlink: None,
         };
 
         Ok(TerminalBuilder {
@@ -474,6 +473,7 @@ pub struct TerminalContent {
     cursor: RenderableCursor,
     cursor_char: char,
     size: TerminalSize,
+    last_hovered_hyperlink: Option<(String, RangeInclusive<Point>)>,
 }
 
 impl Default for TerminalContent {
@@ -490,6 +490,7 @@ impl Default for TerminalContent {
             },
             cursor_char: Default::default(),
             size: Default::default(),
+            last_hovered_hyperlink: None,
         }
     }
 }
@@ -502,7 +503,6 @@ pub struct Terminal {
     pub matches: Vec<RangeInclusive<Point>>,
     last_content: TerminalContent,
     last_synced: Instant,
-    last_hovered_hyperlink: Option<(String, RangeInclusive<Point>)>,
     sync_task: Option<Task<()>>,
     selection_head: Option<Point>,
     breadcrumb_text: String,
@@ -653,7 +653,7 @@ impl Terminal {
             }
             InternalEvent::ScrollToPoint(point) => term.scroll_to_point(*point),
             InternalEvent::Hyperlink(position, open) => {
-                self.last_hovered_hyperlink = None;
+                self.last_content.last_hovered_hyperlink = None;
 
                 let point = grid_point(
                     *position,
@@ -663,12 +663,11 @@ impl Terminal {
 
                 if let Some(url_match) = regex_match_at(term, point, &URL_REGEX) {
                     let url = term.bounds_to_string(*url_match.start(), *url_match.end());
-                    dbg!(&url, &url_match, open);
 
                     if *open {
                         open_uri(&url).log_err();
                     } else {
-                        self.last_hovered_hyperlink = Some((url, url_match));
+                        self.last_content.last_hovered_hyperlink = Some((url, url_match));
                     }
                 }
             }
@@ -779,11 +778,11 @@ impl Terminal {
             self.process_terminal_event(&e, &mut terminal, cx)
         }
 
-        self.last_content = Self::make_content(&terminal, self.last_content.size);
+        self.last_content = Self::make_content(&terminal, &self.last_content);
         self.last_synced = Instant::now();
     }
 
-    fn make_content(term: &Term<ZedListener>, last_size: TerminalSize) -> TerminalContent {
+    fn make_content(term: &Term<ZedListener>, last_content: &TerminalContent) -> TerminalContent {
         let content = term.renderable_content();
         TerminalContent {
             cells: content
@@ -806,7 +805,8 @@ impl Terminal {
             selection: content.selection,
             cursor: content.cursor,
             cursor_char: term.grid()[content.cursor.point].c,
-            size: last_size,
+            size: last_content.size,
+            last_hovered_hyperlink: last_content.last_hovered_hyperlink.clone(),
         }
     }
 
@@ -844,7 +844,7 @@ impl Terminal {
     }
 
     pub fn mouse_move(&mut self, e: &MouseMovedEvent, origin: Vector2F) {
-        self.last_hovered_hyperlink = None;
+        self.last_content.last_hovered_hyperlink = None;
         let position = e.position.sub(origin);
         if self.mouse_mode(e.shift) {
             let point = grid_point(
@@ -882,7 +882,7 @@ impl Terminal {
                     }
                 }
 
-                self.last_hovered_hyperlink = link.map(|link| {
+                self.last_content.last_hovered_hyperlink = link.map(|link| {
                     (
                         link.uri().to_owned(),
                         self.last_content.cells[min_index].point

crates/terminal/src/terminal_element.rs 🔗

@@ -237,7 +237,7 @@ impl TerminalElement {
                 //Layout current cell text
                 {
                     let cell_text = &cell.c.to_string();
-                    if cell_text != " " {
+                    if !is_blank(&cell) {
                         let cell_style = TerminalElement::cell_style(
                             &cell,
                             fg,
@@ -257,8 +257,8 @@ impl TerminalElement {
                             Point::new(line_index as i32, cell.point.column.0 as i32),
                             layout_cell,
                         ))
-                    }
-                };
+                    };
+                }
             }
 
             if cur_rect.is_some() {
@@ -308,7 +308,7 @@ impl TerminalElement {
         let flags = indexed.cell.flags;
         let fg = convert_color(&fg, &style.colors, modal);
 
-        let underline = flags
+        let mut underline = flags
             .intersects(Flags::ALL_UNDERLINES)
             .then(|| Underline {
                 color: Some(fg),
@@ -317,6 +317,13 @@ impl TerminalElement {
             })
             .unwrap_or_default();
 
+        if indexed.cell.hyperlink().is_some() {
+            underline.squiggly = true;
+            if underline.thickness == OrderedFloat(0.) {
+                underline.thickness = OrderedFloat(1.);
+            }
+        }
+
         let mut properties = Properties::new();
         if indexed
             .flags
@@ -569,6 +576,7 @@ impl Element for TerminalElement {
             cursor_char,
             selection,
             cursor,
+            last_hovered_hyperlink,
             ..
         } = &terminal_handle.read(cx).last_content;
 
@@ -824,6 +832,29 @@ impl Element for TerminalElement {
     }
 }
 
+fn is_blank(cell: &IndexedCell) -> bool {
+    if cell.c != ' ' {
+        return false;
+    }
+
+    if cell.bg != AnsiColor::Named(NamedColor::Background) {
+        return false;
+    }
+
+    if cell.hyperlink().is_some() {
+        return false;
+    }
+
+    if cell
+        .flags
+        .intersects(Flags::ALL_UNDERLINES | Flags::INVERSE | Flags::STRIKEOUT)
+    {
+        return false;
+    }
+
+    return true;
+}
+
 fn to_highlighted_range_lines(
     range: &RangeInclusive<Point>,
     layout: &LayoutState,