Merge pull request #676 from nick1udwig/handle-osc-8-links
handle osc 8 links
This commit is contained in:
commit
dae3e28ff4
2 changed files with 82 additions and 6 deletions
|
|
@ -246,6 +246,7 @@ pub struct Terminal {
|
||||||
pub url_regex_search: RegexSearch,
|
pub url_regex_search: RegexSearch,
|
||||||
pub regex_matches: Vec<alacritty_terminal::term::search::Match>,
|
pub regex_matches: Vec<alacritty_terminal::term::search::Match>,
|
||||||
pub active_regex_match: Option<alacritty_terminal::term::search::Match>,
|
pub active_regex_match: Option<alacritty_terminal::term::search::Match>,
|
||||||
|
pub active_hyperlink_id: Option<String>,
|
||||||
bold_font_weight: Weight,
|
bold_font_weight: Weight,
|
||||||
buffer: Arc<Buffer>,
|
buffer: Arc<Buffer>,
|
||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
|
|
@ -335,6 +336,7 @@ impl Terminal {
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
active_regex_match: None,
|
active_regex_match: None,
|
||||||
|
active_hyperlink_id: None,
|
||||||
url_regex_search: url_regex_search(),
|
url_regex_search: url_regex_search(),
|
||||||
regex_matches: Vec::new(),
|
regex_matches: Vec::new(),
|
||||||
bold_font_weight: Weight(bold_font_weight),
|
bold_font_weight: Weight(bold_font_weight),
|
||||||
|
|
@ -887,6 +889,28 @@ impl Terminal {
|
||||||
flags |= Flags::UNDERLINE;
|
flags |= Flags::UNDERLINE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(active_id) = &self.active_hyperlink_id {
|
||||||
|
let mut matches_active = indexed
|
||||||
|
.cell
|
||||||
|
.hyperlink()
|
||||||
|
.is_some_and(|link| link.id() == active_id);
|
||||||
|
if !matches_active
|
||||||
|
&& indexed.cell.flags.intersects(
|
||||||
|
Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER,
|
||||||
|
)
|
||||||
|
&& indexed.point.column.0 > 0
|
||||||
|
{
|
||||||
|
matches_active = grid[Point::new(
|
||||||
|
indexed.point.line,
|
||||||
|
Column(indexed.point.column.0 - 1),
|
||||||
|
)]
|
||||||
|
.hyperlink()
|
||||||
|
.is_some_and(|link| link.id() == active_id);
|
||||||
|
}
|
||||||
|
if matches_active {
|
||||||
|
flags |= Flags::UNDERLINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let metadata = Metadata::new(bg, fg)
|
let metadata = Metadata::new(bg, fg)
|
||||||
.with_flags(flags)
|
.with_flags(flags)
|
||||||
|
|
|
||||||
|
|
@ -336,11 +336,7 @@ where
|
||||||
|
|
||||||
let location = terminal
|
let location = terminal
|
||||||
.viewport_to_point(TermPoint::new(row as usize, TermColumn(col as usize)));
|
.viewport_to_point(TermPoint::new(row as usize, TermColumn(col as usize)));
|
||||||
if terminal
|
if get_hyperlink(&terminal, location).is_some() {
|
||||||
.regex_matches
|
|
||||||
.iter()
|
|
||||||
.any(|bounds| bounds.contains(&location))
|
|
||||||
{
|
|
||||||
return mouse::Interaction::Pointer;
|
return mouse::Interaction::Pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1002,7 +998,10 @@ where
|
||||||
Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => {
|
Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => {
|
||||||
state.modifiers = modifiers;
|
state.modifiers = modifiers;
|
||||||
|
|
||||||
if modifiers.contains(Modifiers::CTRL) || terminal.active_regex_match.is_some() {
|
if modifiers.contains(Modifiers::CTRL)
|
||||||
|
|| terminal.active_regex_match.is_some()
|
||||||
|
|| terminal.active_hyperlink_id.is_some()
|
||||||
|
{
|
||||||
//Might need to update the url regex highlight,
|
//Might need to update the url regex highlight,
|
||||||
//so we need to calculate the mouse position
|
//so we need to calculate the mouse position
|
||||||
let location = if let Some(p) = cursor_position.position() {
|
let location = if let Some(p) = cursor_position.position() {
|
||||||
|
|
@ -1451,6 +1450,9 @@ fn get_hyperlink(
|
||||||
terminal: &std::sync::MutexGuard<'_, Terminal>,
|
terminal: &std::sync::MutexGuard<'_, Terminal>,
|
||||||
location: TermPoint,
|
location: TermPoint,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
|
if let Some(link) = osc8_hyperlink_at(terminal, location) {
|
||||||
|
return Some(link.uri().to_string());
|
||||||
|
}
|
||||||
if let Some(match_) = terminal
|
if let Some(match_) = terminal
|
||||||
.regex_matches
|
.regex_matches
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -1463,6 +1465,32 @@ fn get_hyperlink(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_hyperlink_id(
|
||||||
|
terminal: &std::sync::MutexGuard<'_, Terminal>,
|
||||||
|
location: TermPoint,
|
||||||
|
) -> Option<String> {
|
||||||
|
osc8_hyperlink_at(terminal, location).map(|link| link.id().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn osc8_hyperlink_at(
|
||||||
|
terminal: &std::sync::MutexGuard<'_, Terminal>,
|
||||||
|
location: TermPoint,
|
||||||
|
) -> Option<alacritty_terminal::term::cell::Hyperlink> {
|
||||||
|
let term = terminal.term.lock();
|
||||||
|
let grid = term.grid();
|
||||||
|
let cell = &grid[location];
|
||||||
|
if let Some(link) = cell.hyperlink() {
|
||||||
|
return Some(link);
|
||||||
|
}
|
||||||
|
if cell.flags.intersects(Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER)
|
||||||
|
&& location.column.0 > 0
|
||||||
|
{
|
||||||
|
let left = TermPoint::new(location.line, TermColumn(location.column.0 - 1));
|
||||||
|
return grid[left].hyperlink();
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn update_active_regex_match(
|
fn update_active_regex_match(
|
||||||
terminal: &mut std::sync::MutexGuard<'_, Terminal>,
|
terminal: &mut std::sync::MutexGuard<'_, Terminal>,
|
||||||
location: Option<TermPoint>,
|
location: Option<TermPoint>,
|
||||||
|
|
@ -1475,6 +1503,9 @@ fn update_active_regex_match(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let allow_hyperlink = modifiers
|
||||||
|
.map(|mods| mods.contains(Modifiers::CTRL))
|
||||||
|
.unwrap_or(false);
|
||||||
//Require CTRL for keyboard and mouse interaction
|
//Require CTRL for keyboard and mouse interaction
|
||||||
if let Some(modifiers) = modifiers {
|
if let Some(modifiers) = modifiers {
|
||||||
if !modifiers.contains(Modifiers::CTRL) {
|
if !modifiers.contains(Modifiers::CTRL) {
|
||||||
|
|
@ -1482,16 +1513,37 @@ fn update_active_regex_match(
|
||||||
terminal.active_regex_match = None;
|
terminal.active_regex_match = None;
|
||||||
terminal.needs_update = true;
|
terminal.needs_update = true;
|
||||||
}
|
}
|
||||||
|
if terminal.active_hyperlink_id.is_some() {
|
||||||
|
terminal.active_hyperlink_id = None;
|
||||||
|
terminal.needs_update = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if terminal.active_hyperlink_id.is_some() {
|
||||||
|
terminal.active_hyperlink_id = None;
|
||||||
|
terminal.needs_update = true;
|
||||||
}
|
}
|
||||||
let Some(location) = location else {
|
let Some(location) = location else {
|
||||||
if terminal.active_regex_match.is_some() {
|
if terminal.active_regex_match.is_some() {
|
||||||
terminal.active_regex_match = None;
|
terminal.active_regex_match = None;
|
||||||
terminal.needs_update = true;
|
terminal.needs_update = true;
|
||||||
}
|
}
|
||||||
|
if terminal.active_hyperlink_id.is_some() {
|
||||||
|
terminal.active_hyperlink_id = None;
|
||||||
|
terminal.needs_update = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
if allow_hyperlink {
|
||||||
|
let next_hyperlink_id = get_hyperlink_id(terminal, location);
|
||||||
|
if terminal.active_hyperlink_id != next_hyperlink_id {
|
||||||
|
terminal.active_hyperlink_id = next_hyperlink_id;
|
||||||
|
terminal.needs_update = true;
|
||||||
|
}
|
||||||
|
} else if terminal.active_hyperlink_id.is_some() {
|
||||||
|
terminal.active_hyperlink_id = None;
|
||||||
|
terminal.needs_update = true;
|
||||||
|
}
|
||||||
if let Some(match_) = terminal
|
if let Some(match_) = terminal
|
||||||
.regex_matches
|
.regex_matches
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue