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_CELL_WIDTH: f32 = 5.;
|
||||||
const DEBUG_LINE_HEIGHT: 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
|
///Upward flowing events, for changing the title and such
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
|
@ -105,6 +110,7 @@ enum InternalEvent {
|
||||||
ScrollToPoint(Point),
|
ScrollToPoint(Point),
|
||||||
SetSelection(Option<(Selection, Point)>),
|
SetSelection(Option<(Selection, Point)>),
|
||||||
UpdateSelection(Vector2F),
|
UpdateSelection(Vector2F),
|
||||||
|
HyperlinkHover(Vector2F),
|
||||||
Copy,
|
Copy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,6 +649,16 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InternalEvent::ScrollToPoint(point) => term.scroll_to_point(*point),
|
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) {
|
pub fn mouse_move(&mut self, e: &MouseMovedEvent, origin: Vector2F) {
|
||||||
self.last_hovered_hyperlink = None;
|
self.last_hovered_hyperlink = None;
|
||||||
let position = e.position.sub(origin);
|
let position = e.position.sub(origin);
|
||||||
|
|
||||||
if self.mouse_mode(e.shift) {
|
if self.mouse_mode(e.shift) {
|
||||||
let point = grid_point(
|
let point = grid_point(
|
||||||
position,
|
position,
|
||||||
|
@ -832,9 +847,39 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if e.cmd {
|
} else if e.cmd {
|
||||||
let hyperlink = cell_for_mouse(e.position, &self.last_content)
|
let content_index = content_index_for_mouse(position, &self.last_content);
|
||||||
.cell
|
let link = self.last_content.cells[content_index].hyperlink();
|
||||||
.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);
|
let position = e.position.sub(origin);
|
||||||
if !self.mouse_mode(e.shift) {
|
if !self.mouse_mode(e.shift) {
|
||||||
if e.cmd {
|
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();
|
open_uri(link.uri()).log_err();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1073,7 +1123,7 @@ fn all_search_matches<'a, T>(
|
||||||
RegexIter::new(start, end, AlacDirection::Right, term, regex)
|
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(
|
let col = min(
|
||||||
(pos.x() / content.size.cell_width()) as usize,
|
(pos.x() / content.size.cell_width()) as usize,
|
||||||
content.size.columns() - 1,
|
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,
|
content.size.screen_lines() - 1,
|
||||||
) as usize;
|
) as usize;
|
||||||
|
|
||||||
&content.cells[(line * content.size.columns() + col)]
|
line * content.size.columns() + col
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_uri(uri: &str) -> Result<(), std::io::Error> {
|
fn open_uri(uri: &str) -> Result<(), std::io::Error> {
|
||||||
|
@ -1116,7 +1166,7 @@ mod tests {
|
||||||
use gpui::geometry::vector::vec2f;
|
use gpui::geometry::vector::vec2f;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
use crate::cell_for_mouse;
|
use crate::content_index_for_mouse;
|
||||||
|
|
||||||
use self::terminal_test_context::TerminalTestContext;
|
use self::terminal_test_context::TerminalTestContext;
|
||||||
|
|
||||||
|
@ -1153,7 +1203,10 @@ mod tests {
|
||||||
rng.gen_range(min_col..max_col),
|
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);
|
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!(
|
||||||
assert_eq!(cell_for_mouse(vec2f(1000., 1000.), &content).c, cells[9][9]);
|
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,
|
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:
|
// 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);
|
cx.scene.push_mouse_region(region);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue