mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-25 14:05:41 -05:00
Fix hyperlinks not being keyboard actionable
This fixes a typo in 694a52b
which was filtering all hyperlinks, except
only duplicated ones when opening them with keyboard.
Co-authored-by: Christian Duerr <contact@christianduerr.com>
This commit is contained in:
parent
e09ff0b4b0
commit
40bbdce6de
4 changed files with 74 additions and 32 deletions
|
@ -79,7 +79,7 @@ impl HintState {
|
||||||
|
|
||||||
// Add escape sequence hyperlinks.
|
// Add escape sequence hyperlinks.
|
||||||
if hint.content.hyperlinks {
|
if hint.content.hyperlinks {
|
||||||
self.matches.extend(visible_unique_hyperlink_iter(term));
|
self.matches.extend(visible_unique_hyperlinks_iter(term));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add visible regex matches.
|
// Add visible regex matches.
|
||||||
|
@ -298,7 +298,7 @@ pub fn visible_regex_match_iter<'a, T>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all visible hyperlinks, yanking only unique ones.
|
/// Iterate over all visible hyperlinks, yanking only unique ones.
|
||||||
pub fn visible_unique_hyperlink_iter<T>(term: &Term<T>) -> impl Iterator<Item = Match> + '_ {
|
pub fn visible_unique_hyperlinks_iter<T>(term: &Term<T>) -> impl Iterator<Item = Match> + '_ {
|
||||||
let mut display_iter = term.grid().display_iter().peekable();
|
let mut display_iter = term.grid().display_iter().peekable();
|
||||||
|
|
||||||
// Avoid creating hints for the same hyperlinks, but from a different places.
|
// Avoid creating hints for the same hyperlinks, but from a different places.
|
||||||
|
@ -308,7 +308,7 @@ pub fn visible_unique_hyperlink_iter<T>(term: &Term<T>) -> impl Iterator<Item =
|
||||||
// Find the start of the next unique hyperlink.
|
// Find the start of the next unique hyperlink.
|
||||||
let (cell, hyperlink) = display_iter.find_map(|cell| {
|
let (cell, hyperlink) = display_iter.find_map(|cell| {
|
||||||
let hyperlink = cell.hyperlink()?;
|
let hyperlink = cell.hyperlink()?;
|
||||||
unique_hyperlinks.contains(&hyperlink).then(|| {
|
(!unique_hyperlinks.contains(&hyperlink)).then(|| {
|
||||||
unique_hyperlinks.insert(hyperlink.clone());
|
unique_hyperlinks.insert(hyperlink.clone());
|
||||||
(cell, hyperlink)
|
(cell, hyperlink)
|
||||||
})
|
})
|
||||||
|
@ -582,6 +582,7 @@ impl<'a, T> Iterator for HintPostProcessor<'a, T> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use alacritty_terminal::ansi::Handler;
|
||||||
use alacritty_terminal::index::{Column, Line};
|
use alacritty_terminal::index::{Column, Line};
|
||||||
use alacritty_terminal::term::test::mock_term;
|
use alacritty_terminal::term::test::mock_term;
|
||||||
|
|
||||||
|
@ -642,4 +643,41 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(count, 0);
|
assert_eq!(count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn collect_unique_hyperlinks() {
|
||||||
|
let mut term = mock_term("000\r\n111");
|
||||||
|
term.goto(Line(0), Column(0));
|
||||||
|
|
||||||
|
let hyperlink_foo = Hyperlink::new(Some("1"), "foo");
|
||||||
|
let hyperlink_bar = Hyperlink::new(Some("2"), "bar");
|
||||||
|
|
||||||
|
// Create 2 hyperlinks on the first line.
|
||||||
|
term.set_hyperlink(Some(hyperlink_foo.clone()));
|
||||||
|
term.input('b');
|
||||||
|
term.input('a');
|
||||||
|
term.set_hyperlink(Some(hyperlink_bar.clone()));
|
||||||
|
term.input('r');
|
||||||
|
term.set_hyperlink(Some(hyperlink_foo.clone()));
|
||||||
|
term.goto(Line(1), Column(0));
|
||||||
|
|
||||||
|
// Ditto for the second line.
|
||||||
|
term.set_hyperlink(Some(hyperlink_foo));
|
||||||
|
term.input('b');
|
||||||
|
term.input('a');
|
||||||
|
term.set_hyperlink(Some(hyperlink_bar));
|
||||||
|
term.input('r');
|
||||||
|
term.set_hyperlink(None);
|
||||||
|
|
||||||
|
let mut unique_hyperlinks = visible_unique_hyperlinks_iter(&term);
|
||||||
|
assert_eq!(
|
||||||
|
Some(Match::new(Point::new(Line(0), Column(0)), Point::new(Line(0), Column(1)))),
|
||||||
|
unique_hyperlinks.next()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(Match::new(Point::new(Line(0), Column(2)), Point::new(Line(0), Column(2)))),
|
||||||
|
unique_hyperlinks.next()
|
||||||
|
);
|
||||||
|
assert_eq!(None, unique_hyperlinks.next());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,7 @@ pub trait EventListener {
|
||||||
fn send_event(&self, _event: Event) {}
|
fn send_event(&self, _event: Event) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Placeholder implementation for tests.
|
/// Null sink for events.
|
||||||
#[cfg(test)]
|
pub struct VoidListener;
|
||||||
impl EventListener for () {}
|
|
||||||
|
impl EventListener for VoidListener {}
|
||||||
|
|
|
@ -2089,6 +2089,7 @@ pub mod test {
|
||||||
use unicode_width::UnicodeWidthChar;
|
use unicode_width::UnicodeWidthChar;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
use crate::event::VoidListener;
|
||||||
use crate::index::Column;
|
use crate::index::Column;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
@ -2136,7 +2137,7 @@ pub mod test {
|
||||||
/// hello\n:)\r\ntest",
|
/// hello\n:)\r\ntest",
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub fn mock_term(content: &str) -> Term<()> {
|
pub fn mock_term(content: &str) -> Term<VoidListener> {
|
||||||
let lines: Vec<&str> = content.split('\n').collect();
|
let lines: Vec<&str> = content.split('\n').collect();
|
||||||
let num_cols = lines
|
let num_cols = lines
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -2146,7 +2147,7 @@ pub mod test {
|
||||||
|
|
||||||
// Create terminal with the appropriate dimensions.
|
// Create terminal with the appropriate dimensions.
|
||||||
let size = TermSize::new(num_cols, lines.len());
|
let size = TermSize::new(num_cols, lines.len());
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Fill terminal with content.
|
// Fill terminal with content.
|
||||||
for (line, text) in lines.iter().enumerate() {
|
for (line, text) in lines.iter().enumerate() {
|
||||||
|
@ -2182,6 +2183,7 @@ mod tests {
|
||||||
|
|
||||||
use crate::ansi::{self, CharsetIndex, Handler, StandardCharset};
|
use crate::ansi::{self, CharsetIndex, Handler, StandardCharset};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
use crate::event::VoidListener;
|
||||||
use crate::grid::{Grid, Scroll};
|
use crate::grid::{Grid, Scroll};
|
||||||
use crate::index::{Column, Point, Side};
|
use crate::index::{Column, Point, Side};
|
||||||
use crate::selection::{Selection, SelectionType};
|
use crate::selection::{Selection, SelectionType};
|
||||||
|
@ -2191,7 +2193,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn scroll_display_page_up() {
|
fn scroll_display_page_up() {
|
||||||
let size = TermSize::new(5, 10);
|
let size = TermSize::new(5, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 11 lines of scrollback.
|
// Create 11 lines of scrollback.
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
|
@ -2217,7 +2219,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn scroll_display_page_down() {
|
fn scroll_display_page_down() {
|
||||||
let size = TermSize::new(5, 10);
|
let size = TermSize::new(5, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 11 lines of scrollback.
|
// Create 11 lines of scrollback.
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
|
@ -2247,7 +2249,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn simple_selection_works() {
|
fn simple_selection_works() {
|
||||||
let size = TermSize::new(5, 5);
|
let size = TermSize::new(5, 5);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
let grid = term.grid_mut();
|
let grid = term.grid_mut();
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
|
@ -2293,7 +2295,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn semantic_selection_works() {
|
fn semantic_selection_works() {
|
||||||
let size = TermSize::new(5, 3);
|
let size = TermSize::new(5, 3);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
let mut grid: Grid<Cell> = Grid::new(3, 5, 0);
|
let mut grid: Grid<Cell> = Grid::new(3, 5, 0);
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
for j in 0..2 {
|
for j in 0..2 {
|
||||||
|
@ -2341,7 +2343,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn line_selection_works() {
|
fn line_selection_works() {
|
||||||
let size = TermSize::new(5, 1);
|
let size = TermSize::new(5, 1);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
let mut grid: Grid<Cell> = Grid::new(1, 5, 0);
|
let mut grid: Grid<Cell> = Grid::new(1, 5, 0);
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
grid[Line(0)][Column(i)].c = 'a';
|
grid[Line(0)][Column(i)].c = 'a';
|
||||||
|
@ -2362,7 +2364,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn block_selection_works() {
|
fn block_selection_works() {
|
||||||
let size = TermSize::new(5, 5);
|
let size = TermSize::new(5, 5);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
let grid = term.grid_mut();
|
let grid = term.grid_mut();
|
||||||
for i in 1..4 {
|
for i in 1..4 {
|
||||||
grid[Line(i)][Column(0)].c = '"';
|
grid[Line(i)][Column(0)].c = '"';
|
||||||
|
@ -2418,7 +2420,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn input_line_drawing_character() {
|
fn input_line_drawing_character() {
|
||||||
let size = TermSize::new(7, 17);
|
let size = TermSize::new(7, 17);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
let cursor = Point::new(Line(0), Column(0));
|
let cursor = Point::new(Line(0), Column(0));
|
||||||
term.configure_charset(CharsetIndex::G0, StandardCharset::SpecialCharacterAndLineDrawing);
|
term.configure_charset(CharsetIndex::G0, StandardCharset::SpecialCharacterAndLineDrawing);
|
||||||
term.input('a');
|
term.input('a');
|
||||||
|
@ -2429,7 +2431,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn clearing_viewport_keeps_history_position() {
|
fn clearing_viewport_keeps_history_position() {
|
||||||
let size = TermSize::new(10, 20);
|
let size = TermSize::new(10, 20);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 10 lines of scrollback.
|
// Create 10 lines of scrollback.
|
||||||
for _ in 0..29 {
|
for _ in 0..29 {
|
||||||
|
@ -2450,7 +2452,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn clearing_viewport_with_vi_mode_keeps_history_position() {
|
fn clearing_viewport_with_vi_mode_keeps_history_position() {
|
||||||
let size = TermSize::new(10, 20);
|
let size = TermSize::new(10, 20);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 10 lines of scrollback.
|
// Create 10 lines of scrollback.
|
||||||
for _ in 0..29 {
|
for _ in 0..29 {
|
||||||
|
@ -2476,7 +2478,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn clearing_scrollback_resets_display_offset() {
|
fn clearing_scrollback_resets_display_offset() {
|
||||||
let size = TermSize::new(10, 20);
|
let size = TermSize::new(10, 20);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 10 lines of scrollback.
|
// Create 10 lines of scrollback.
|
||||||
for _ in 0..29 {
|
for _ in 0..29 {
|
||||||
|
@ -2497,7 +2499,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn clearing_scrollback_sets_vi_cursor_into_viewport() {
|
fn clearing_scrollback_sets_vi_cursor_into_viewport() {
|
||||||
let size = TermSize::new(10, 20);
|
let size = TermSize::new(10, 20);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 10 lines of scrollback.
|
// Create 10 lines of scrollback.
|
||||||
for _ in 0..29 {
|
for _ in 0..29 {
|
||||||
|
@ -2523,7 +2525,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn clear_saved_lines() {
|
fn clear_saved_lines() {
|
||||||
let size = TermSize::new(7, 17);
|
let size = TermSize::new(7, 17);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Add one line of scrollback.
|
// Add one line of scrollback.
|
||||||
term.grid.scroll_up(&(Line(0)..Line(1)), 1);
|
term.grid.scroll_up(&(Line(0)..Line(1)), 1);
|
||||||
|
@ -2545,7 +2547,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn vi_cursor_keep_pos_on_scrollback_buffer() {
|
fn vi_cursor_keep_pos_on_scrollback_buffer() {
|
||||||
let size = TermSize::new(5, 10);
|
let size = TermSize::new(5, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 11 lines of scrollback.
|
// Create 11 lines of scrollback.
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
|
@ -2565,7 +2567,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn grow_lines_updates_active_cursor_pos() {
|
fn grow_lines_updates_active_cursor_pos() {
|
||||||
let mut size = TermSize::new(100, 10);
|
let mut size = TermSize::new(100, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 10 lines of scrollback.
|
// Create 10 lines of scrollback.
|
||||||
for _ in 0..19 {
|
for _ in 0..19 {
|
||||||
|
@ -2585,7 +2587,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn grow_lines_updates_inactive_cursor_pos() {
|
fn grow_lines_updates_inactive_cursor_pos() {
|
||||||
let mut size = TermSize::new(100, 10);
|
let mut size = TermSize::new(100, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 10 lines of scrollback.
|
// Create 10 lines of scrollback.
|
||||||
for _ in 0..19 {
|
for _ in 0..19 {
|
||||||
|
@ -2611,7 +2613,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn shrink_lines_updates_active_cursor_pos() {
|
fn shrink_lines_updates_active_cursor_pos() {
|
||||||
let mut size = TermSize::new(100, 10);
|
let mut size = TermSize::new(100, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 10 lines of scrollback.
|
// Create 10 lines of scrollback.
|
||||||
for _ in 0..19 {
|
for _ in 0..19 {
|
||||||
|
@ -2631,7 +2633,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn shrink_lines_updates_inactive_cursor_pos() {
|
fn shrink_lines_updates_inactive_cursor_pos() {
|
||||||
let mut size = TermSize::new(100, 10);
|
let mut size = TermSize::new(100, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Create 10 lines of scrollback.
|
// Create 10 lines of scrollback.
|
||||||
for _ in 0..19 {
|
for _ in 0..19 {
|
||||||
|
@ -2657,7 +2659,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn damage_public_usage() {
|
fn damage_public_usage() {
|
||||||
let size = TermSize::new(10, 10);
|
let size = TermSize::new(10, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
// Reset terminal for partial damage tests since it's initialized as fully damaged.
|
// Reset terminal for partial damage tests since it's initialized as fully damaged.
|
||||||
term.reset_damage();
|
term.reset_damage();
|
||||||
|
|
||||||
|
@ -2750,7 +2752,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn damage_cursor_movements() {
|
fn damage_cursor_movements() {
|
||||||
let size = TermSize::new(10, 10);
|
let size = TermSize::new(10, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
let num_cols = term.columns();
|
let num_cols = term.columns();
|
||||||
// Reset terminal for partial damage tests since it's initialized as fully damaged.
|
// Reset terminal for partial damage tests since it's initialized as fully damaged.
|
||||||
term.reset_damage();
|
term.reset_damage();
|
||||||
|
@ -2848,7 +2850,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn full_damage() {
|
fn full_damage() {
|
||||||
let size = TermSize::new(100, 10);
|
let size = TermSize::new(100, 10);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
assert!(term.damage.is_fully_damaged);
|
assert!(term.damage.is_fully_damaged);
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
|
@ -2934,7 +2936,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn window_title() {
|
fn window_title() {
|
||||||
let size = TermSize::new(7, 17);
|
let size = TermSize::new(7, 17);
|
||||||
let mut term = Term::new(&Config::default(), &size, ());
|
let mut term = Term::new(&Config::default(), &size, VoidListener);
|
||||||
|
|
||||||
// Title None by default.
|
// Title None by default.
|
||||||
assert_eq!(term.title, None);
|
assert_eq!(term.title, None);
|
||||||
|
|
|
@ -380,13 +380,14 @@ mod tests {
|
||||||
|
|
||||||
use crate::ansi::Handler;
|
use crate::ansi::Handler;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
use crate::event::VoidListener;
|
||||||
use crate::index::{Column, Line};
|
use crate::index::{Column, Line};
|
||||||
use crate::term::test::TermSize;
|
use crate::term::test::TermSize;
|
||||||
use crate::term::Term;
|
use crate::term::Term;
|
||||||
|
|
||||||
fn term() -> Term<()> {
|
fn term() -> Term<VoidListener> {
|
||||||
let size = TermSize::new(20, 20);
|
let size = TermSize::new(20, 20);
|
||||||
Term::new(&Config::default(), &size, ())
|
Term::new(&Config::default(), &size, VoidListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -493,7 +494,7 @@ mod tests {
|
||||||
assert_eq!(cursor.point, Point::new(Line(0), Column(0)));
|
assert_eq!(cursor.point, Point::new(Line(0), Column(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn motion_semantic_term() -> Term<()> {
|
fn motion_semantic_term() -> Term<VoidListener> {
|
||||||
let mut term = term();
|
let mut term = term();
|
||||||
|
|
||||||
term.grid_mut()[Line(0)][Column(0)].c = 'x';
|
term.grid_mut()[Line(0)][Column(0)].c = 'x';
|
||||||
|
|
Loading…
Reference in a new issue