mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-12 05:15:00 +00:00
WIP hyperlink detection
This commit is contained in:
parent
9f81f39f51
commit
b8f362fd84
2 changed files with 80 additions and 26 deletions
|
@ -83,6 +83,11 @@ const DEBUG_TERMINAL_HEIGHT: f32 = 30.;
|
|||
const DEBUG_CELL_WIDTH: f32 = 5.;
|
||||
const DEBUG_LINE_HEIGHT: f32 = 5.;
|
||||
|
||||
/// Copied from alacritty's ui_config.rs
|
||||
const URL_REGEX: &str =
|
||||
"(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)\
|
||||
[^\u{0000}-\u{001F}\u{007F}-\u{009F}<>\"\\s{-}\\^⟨⟩`]+";
|
||||
|
||||
///Upward flowing events, for changing the title and such
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Event {
|
||||
|
@ -105,6 +110,7 @@ enum InternalEvent {
|
|||
ScrollToPoint(Point),
|
||||
SetSelection(Option<(Selection, Point)>),
|
||||
UpdateSelection(Vector2F),
|
||||
HyperlinkHover(Vector2F),
|
||||
Copy,
|
||||
}
|
||||
|
||||
|
@ -643,6 +649,16 @@ impl Terminal {
|
|||
}
|
||||
}
|
||||
InternalEvent::ScrollToPoint(point) => term.scroll_to_point(*point),
|
||||
InternalEvent::HyperlinkHover(position) => {
|
||||
let point = grid_point(
|
||||
*position,
|
||||
self.last_content.size,
|
||||
term.grid().display_offset(),
|
||||
);
|
||||
let side = mouse_side(*position, self.last_content.size);
|
||||
|
||||
println!("Hyperlink hover")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,7 +833,6 @@ impl Terminal {
|
|||
pub fn mouse_move(&mut self, e: &MouseMovedEvent, origin: Vector2F) {
|
||||
self.last_hovered_hyperlink = None;
|
||||
let position = e.position.sub(origin);
|
||||
|
||||
if self.mouse_mode(e.shift) {
|
||||
let point = grid_point(
|
||||
position,
|
||||
|
@ -832,9 +847,39 @@ impl Terminal {
|
|||
}
|
||||
}
|
||||
} else if e.cmd {
|
||||
let hyperlink = cell_for_mouse(e.position, &self.last_content)
|
||||
.cell
|
||||
.hyperlink();
|
||||
let content_index = content_index_for_mouse(position, &self.last_content);
|
||||
let link = self.last_content.cells[content_index].hyperlink();
|
||||
|
||||
if link.is_some() {
|
||||
let mut min_index = content_index;
|
||||
loop {
|
||||
if self.last_content.cells[min_index - 1].hyperlink() == link {
|
||||
min_index = min_index - 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let mut max_index = content_index;
|
||||
loop {
|
||||
if self.last_content.cells[max_index + 1].hyperlink() == link {
|
||||
max_index = max_index + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.last_hovered_hyperlink = link.map(|link| {
|
||||
(
|
||||
link,
|
||||
self.last_content.cells[min_index].point
|
||||
..self.last_content.cells[max_index].point,
|
||||
)
|
||||
});
|
||||
} else {
|
||||
self.events
|
||||
.push_back(InternalEvent::HyperlinkHover(position));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,7 +948,12 @@ impl Terminal {
|
|||
let position = e.position.sub(origin);
|
||||
if !self.mouse_mode(e.shift) {
|
||||
if e.cmd {
|
||||
if let Some(link) = cell_for_mouse(position, &self.last_content).hyperlink() {
|
||||
if let Some(link) = self.last_content.cells
|
||||
[content_index_for_mouse(position, &self.last_content)]
|
||||
.hyperlink()
|
||||
{
|
||||
dbg!(&link);
|
||||
dbg!(&self.last_hovered_hyperlink);
|
||||
open_uri(link.uri()).log_err();
|
||||
}
|
||||
} else {
|
||||
|
@ -1073,7 +1123,7 @@ fn all_search_matches<'a, T>(
|
|||
RegexIter::new(start, end, AlacDirection::Right, term, regex)
|
||||
}
|
||||
|
||||
fn cell_for_mouse<'a>(pos: Vector2F, content: &'a TerminalContent) -> &'a IndexedCell {
|
||||
fn content_index_for_mouse<'a>(pos: Vector2F, content: &'a TerminalContent) -> usize {
|
||||
let col = min(
|
||||
(pos.x() / content.size.cell_width()) as usize,
|
||||
content.size.columns() - 1,
|
||||
|
@ -1083,7 +1133,7 @@ fn cell_for_mouse<'a>(pos: Vector2F, content: &'a TerminalContent) -> &'a Indexe
|
|||
content.size.screen_lines() - 1,
|
||||
) as usize;
|
||||
|
||||
&content.cells[(line * content.size.columns() + col)]
|
||||
line * content.size.columns() + col
|
||||
}
|
||||
|
||||
fn open_uri(uri: &str) -> Result<(), std::io::Error> {
|
||||
|
@ -1116,7 +1166,7 @@ mod tests {
|
|||
use gpui::geometry::vector::vec2f;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::cell_for_mouse;
|
||||
use crate::content_index_for_mouse;
|
||||
|
||||
use self::terminal_test_context::TerminalTestContext;
|
||||
|
||||
|
@ -1153,7 +1203,10 @@ mod tests {
|
|||
rng.gen_range(min_col..max_col),
|
||||
);
|
||||
|
||||
assert_eq!(cell_for_mouse(mouse_pos, &content).c, cells[j][i]);
|
||||
assert_eq!(
|
||||
content.cells[content_index_for_mouse(mouse_pos, &content)].c,
|
||||
cells[j][i]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1172,7 +1225,13 @@ mod tests {
|
|||
|
||||
let (content, cells) = TerminalTestContext::create_terminal_content(size, &mut rng);
|
||||
|
||||
assert_eq!(cell_for_mouse(vec2f(-10., -10.), &content).c, cells[0][0]);
|
||||
assert_eq!(cell_for_mouse(vec2f(1000., 1000.), &content).c, cells[9][9]);
|
||||
assert_eq!(
|
||||
content.cells[content_index_for_mouse(vec2f(-10., -10.), &content)].c,
|
||||
cells[0][0]
|
||||
);
|
||||
assert_eq!(
|
||||
content.cells[content_index_for_mouse(vec2f(1000., 1000.), &content)].c,
|
||||
cells[9][9]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -427,6 +427,16 @@ impl TerminalElement {
|
|||
position: e.position,
|
||||
});
|
||||
}
|
||||
})
|
||||
.on_move(move |event, cx| {
|
||||
if cx.is_parent_view_focused() {
|
||||
if let Some(conn_handle) = connection.upgrade(cx.app) {
|
||||
conn_handle.update(cx.app, |terminal, cx| {
|
||||
terminal.mouse_move(&event, origin);
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Mouse mode handlers:
|
||||
|
@ -474,21 +484,6 @@ impl TerminalElement {
|
|||
),
|
||||
)
|
||||
}
|
||||
//Mouse move manages both dragging and motion events
|
||||
if mode.intersects(TermMode::MOUSE_DRAG | TermMode::MOUSE_MOTION) {
|
||||
region = region
|
||||
//TODO: This does not fire on right-mouse-down-move events.
|
||||
.on_move(move |event, cx| {
|
||||
if cx.is_parent_view_focused() {
|
||||
if let Some(conn_handle) = connection.upgrade(cx.app) {
|
||||
conn_handle.update(cx.app, |terminal, cx| {
|
||||
terminal.mouse_move(&event, origin);
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
cx.scene.push_mouse_region(region);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue