WIP hyperlink searching
This commit is contained in:
parent
b3202c382d
commit
f706cbe143
1 changed files with 42 additions and 11 deletions
|
@ -14,7 +14,7 @@ use alacritty_terminal::{
|
||||||
selection::{Selection, SelectionRange, SelectionType},
|
selection::{Selection, SelectionRange, SelectionType},
|
||||||
sync::FairMutex,
|
sync::FairMutex,
|
||||||
term::{
|
term::{
|
||||||
cell::{Cell, Hyperlink},
|
cell::Cell,
|
||||||
color::Rgb,
|
color::Rgb,
|
||||||
search::{Match, RegexIter, RegexSearch},
|
search::{Match, RegexIter, RegexSearch},
|
||||||
RenderableCursor, TermMode,
|
RenderableCursor, TermMode,
|
||||||
|
@ -43,7 +43,7 @@ use std::{
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
io,
|
io,
|
||||||
ops::{Deref, Range, RangeInclusive, Sub},
|
ops::{Deref, RangeInclusive, Sub},
|
||||||
os::unix::{prelude::AsRawFd, process::CommandExt},
|
os::unix::{prelude::AsRawFd, process::CommandExt},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::Command,
|
process::Command,
|
||||||
|
@ -77,16 +77,14 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
///Scroll multiplier that is set to 3 by default. This will be removed when I
|
///Scroll multiplier that is set to 3 by default. This will be removed when I
|
||||||
///Implement scroll bars.
|
///Implement scroll bars.
|
||||||
const SCROLL_MULTIPLIER: f32 = 4.;
|
const SCROLL_MULTIPLIER: f32 = 4.;
|
||||||
// const MAX_SEARCH_LINES: usize = 100;
|
const MAX_SEARCH_LINES: usize = 100;
|
||||||
const DEBUG_TERMINAL_WIDTH: f32 = 500.;
|
const DEBUG_TERMINAL_WIDTH: f32 = 500.;
|
||||||
const DEBUG_TERMINAL_HEIGHT: f32 = 30.;
|
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
|
/// Copied from alacritty's ui_config.rs
|
||||||
const URL_REGEX: &str =
|
static URL_REGEX: RegexSearch = RegexSearch::new("(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\u{0000}-\u{001F}\u{007F}-\u{009F}<>\"\\s{-}\\^⟨⟩`]+").unwrap();
|
||||||
"(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)]
|
||||||
|
@ -500,7 +498,7 @@ pub struct Terminal {
|
||||||
pub matches: Vec<RangeInclusive<Point>>,
|
pub matches: Vec<RangeInclusive<Point>>,
|
||||||
last_content: TerminalContent,
|
last_content: TerminalContent,
|
||||||
last_synced: Instant,
|
last_synced: Instant,
|
||||||
last_hovered_hyperlink: Option<(Hyperlink, Range<Point>)>,
|
last_hovered_hyperlink: Option<(String, RangeInclusive<Point>)>,
|
||||||
sync_task: Option<Task<()>>,
|
sync_task: Option<Task<()>>,
|
||||||
selection_head: Option<Point>,
|
selection_head: Option<Point>,
|
||||||
breadcrumb_text: String,
|
breadcrumb_text: String,
|
||||||
|
@ -651,14 +649,23 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
InternalEvent::ScrollToPoint(point) => term.scroll_to_point(*point),
|
InternalEvent::ScrollToPoint(point) => term.scroll_to_point(*point),
|
||||||
InternalEvent::Hyperlink(position, open) => {
|
InternalEvent::Hyperlink(position, open) => {
|
||||||
|
self.last_hovered_hyperlink = None;
|
||||||
|
|
||||||
let point = grid_point(
|
let point = grid_point(
|
||||||
*position,
|
*position,
|
||||||
self.last_content.size,
|
self.last_content.size,
|
||||||
term.grid().display_offset(),
|
term.grid().display_offset(),
|
||||||
);
|
);
|
||||||
let side = mouse_side(*position, self.last_content.size);
|
|
||||||
|
|
||||||
println!("Hyperlink hover | click ")
|
if let Some(url_match) = regex_match_at(term, point, &URL_REGEX) {
|
||||||
|
let url = term.bounds_to_string(*url_match.start(), *url_match.end());
|
||||||
|
|
||||||
|
if *open {
|
||||||
|
open_uri(&url).log_err();
|
||||||
|
} else {
|
||||||
|
self.last_hovered_hyperlink = Some((url, url_match));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -872,9 +879,9 @@ impl Terminal {
|
||||||
|
|
||||||
self.last_hovered_hyperlink = link.map(|link| {
|
self.last_hovered_hyperlink = link.map(|link| {
|
||||||
(
|
(
|
||||||
link,
|
link.uri().to_owned(),
|
||||||
self.last_content.cells[min_index].point
|
self.last_content.cells[min_index].point
|
||||||
..self.last_content.cells[max_index].point,
|
..=self.last_content.cells[max_index].point,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -1112,6 +1119,30 @@ impl Entity for Terminal {
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Based on alacritty/src/display/hint.rs > regex_match_at
|
||||||
|
/// Retrieve the match, if the specified point is inside the content matching the regex.
|
||||||
|
fn regex_match_at<T>(term: &Term<T>, point: Point, regex: &RegexSearch) -> Option<Match> {
|
||||||
|
visible_regex_match_iter(term, regex).find(|rm| rm.contains(&point))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copied from alacritty/src/display/hint.rs:
|
||||||
|
/// Iterate over all visible regex matches.
|
||||||
|
pub fn visible_regex_match_iter<'a, T>(
|
||||||
|
term: &'a Term<T>,
|
||||||
|
regex: &'a RegexSearch,
|
||||||
|
) -> impl Iterator<Item = Match> + 'a {
|
||||||
|
let viewport_start = Line(-(term.grid().display_offset() as i32));
|
||||||
|
let viewport_end = viewport_start + term.bottommost_line();
|
||||||
|
let mut start = term.line_search_left(Point::new(viewport_start, Column(0)));
|
||||||
|
let mut end = term.line_search_right(Point::new(viewport_end, Column(0)));
|
||||||
|
start.line = start.line.max(viewport_start - MAX_SEARCH_LINES);
|
||||||
|
end.line = end.line.min(viewport_end + MAX_SEARCH_LINES);
|
||||||
|
|
||||||
|
RegexIter::new(start, end, AlacDirection::Right, term, regex)
|
||||||
|
.skip_while(move |rm| rm.end().line < viewport_start)
|
||||||
|
.take_while(move |rm| rm.start().line <= viewport_end)
|
||||||
|
}
|
||||||
|
|
||||||
fn make_selection(range: &RangeInclusive<Point>) -> Selection {
|
fn make_selection(range: &RangeInclusive<Point>) -> Selection {
|
||||||
let mut selection = Selection::new(SelectionType::Simple, *range.start(), AlacDirection::Left);
|
let mut selection = Selection::new(SelectionType::Simple, *range.start(), AlacDirection::Left);
|
||||||
selection.update(*range.end(), AlacDirection::Right);
|
selection.update(*range.end(), AlacDirection::Right);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue