summaryrefslogtreecommitdiff
path: root/alacritty_terminal/src/term/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty_terminal/src/term/mod.rs')
-rw-r--r--alacritty_terminal/src/term/mod.rs179
1 files changed, 100 insertions, 79 deletions
diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs
index 691a4fe1..0cc2cd6d 100644
--- a/alacritty_terminal/src/term/mod.rs
+++ b/alacritty_terminal/src/term/mod.rs
@@ -20,17 +20,17 @@ use std::{io, mem, ptr};
use font::{self, Size};
use glutin::MouseCursor;
+use rfind_url::{Parser, ParserState};
use unicode_width::UnicodeWidthChar;
use crate::ansi::{
- self, Attr, CharsetIndex, Color, CursorStyle, Handler, NamedColor, StandardCharset,
+ self, Attr, CharsetIndex, Color, CursorStyle, Handler, NamedColor, StandardCharset, TermInfo,
};
use crate::clipboard::{Clipboard, ClipboardType};
use crate::config::{Config, VisualBellAnimation};
use crate::cursor::CursorKey;
use crate::grid::{
BidirectionalIterator, DisplayIter, Grid, GridCell, IndexRegion, Indexed, Scroll,
- ViewportPosition,
};
use crate::index::{self, Column, Contains, IndexRange, Line, Linear, Point};
use crate::input::FONT_SIZE_STEP;
@@ -38,7 +38,7 @@ use crate::message_bar::MessageBuffer;
use crate::selection::{self, Selection, SelectionRange, Span};
use crate::term::cell::{Cell, Flags, LineLength};
use crate::term::color::Rgb;
-use crate::url::{Url, UrlParser};
+use crate::url::Url;
#[cfg(windows)]
use crate::tty;
@@ -58,8 +58,6 @@ pub trait Search {
fn semantic_search_left(&self, _: Point<usize>) -> Point<usize>;
/// Find the nearest semantic boundary _to the point_ of provided point.
fn semantic_search_right(&self, _: Point<usize>) -> Point<usize>;
- /// Find the nearest URL boundary in both directions.
- fn url_search(&self, _: Point<usize>) -> Option<Url>;
/// Find the nearest matching bracket.
fn bracket_search(&self, _: Point<usize>) -> Option<Point<usize>>;
}
@@ -77,11 +75,11 @@ impl Search for Term {
break;
}
- if iter.cur.col == last_col && !cell.flags.contains(cell::Flags::WRAPLINE) {
+ if iter.point().col == last_col && !cell.flags.contains(cell::Flags::WRAPLINE) {
break; // cut off if on new line or hit escape char
}
- point = iter.cur;
+ point = iter.point();
}
point
@@ -99,7 +97,7 @@ impl Search for Term {
break;
}
- point = iter.cur;
+ point = iter.point();
if point.col == last_col && !cell.flags.contains(cell::Flags::WRAPLINE) {
break; // cut off if on new line or hit escape char
@@ -109,40 +107,6 @@ impl Search for Term {
point
}
- fn url_search(&self, mut point: Point<usize>) -> Option<Url> {
- let last_col = self.grid.num_cols() - 1;
-
- // Switch first line from top to bottom
- point.line = self.grid.num_lines().0 - point.line - 1;
-
- // Remove viewport scroll offset
- point.line += self.grid.display_offset();
-
- // Create forwards and backwards iterators
- let mut iterf = self.grid.iter_from(point);
- point.col += 1;
- let mut iterb = self.grid.iter_from(point);
-
- // Find URLs
- let mut url_parser = UrlParser::new();
- while let Some(cell) = iterb.prev() {
- if (iterb.cur.col == last_col && !cell.flags.contains(cell::Flags::WRAPLINE))
- || url_parser.advance_left(cell)
- {
- break;
- }
- }
-
- while let Some(cell) = iterf.next() {
- if url_parser.advance_right(cell)
- || (iterf.cur.col == last_col && !cell.flags.contains(cell::Flags::WRAPLINE))
- {
- break;
- }
- }
- url_parser.url()
- }
-
fn bracket_search(&self, point: Point<usize>) -> Option<Point<usize>> {
let start_char = self.grid[point.line][point.col].c;
@@ -175,7 +139,7 @@ impl Search for Term {
// Check if the bracket matches
if c == end_char && skip_pairs == 0 {
- return Some(iter.cur);
+ return Some(iter.point());
} else if c == start_char {
skip_pairs += 1;
} else if c == end_char {
@@ -235,44 +199,27 @@ impl<'a> RenderableCellsIter<'a> {
let cursor_offset = grid.line_to_offset(term.cursor.point.line);
let inner = grid.display_iter();
- let selection_range = selection.and_then(|span| {
- // Get on-screen lines of the selection's locations
- let start_line = grid.buffer_line_to_visible(span.start.line);
- let end_line = grid.buffer_line_to_visible(span.end.line);
-
- // Limit block selection columns to within start/end points
- let (limit_start, limit_end) =
- if span.is_block { (span.start.col, span.end.col) } else { (Column(0), Column(0)) };
-
- // Get start/end locations based on what part of selection is on screen
- let locations = match (start_line, end_line) {
- (ViewportPosition::Visible(start_line), ViewportPosition::Visible(end_line)) => {
- Some((start_line, span.start.col, end_line, span.end.col))
- },
- (ViewportPosition::Visible(start_line), ViewportPosition::Above) => {
- Some((start_line, span.start.col, Line(0), limit_end))
- },
- (ViewportPosition::Below, ViewportPosition::Visible(end_line)) => {
- Some((grid.num_lines(), limit_start, end_line, span.end.col))
- },
- (ViewportPosition::Below, ViewportPosition::Above) => {
- Some((grid.num_lines(), limit_start, Line(0), limit_end))
- },
- _ => None,
+ let selection_range = selection.map(|span| {
+ let (limit_start, limit_end) = if span.is_block {
+ (span.end.col, span.start.col)
+ } else {
+ (Column(0), term.cols() - 1)
};
- locations.map(|(start_line, start_col, end_line, end_col)| {
- // start and end *lines* are swapped as we switch from buffer to
- // Line coordinates.
- let mut end = Point { line: start_line, col: start_col };
- let mut start = Point { line: end_line, col: end_col };
+ // Get on-screen lines of the selection's locations
+ let mut start = term.buffer_to_visible(span.start);
+ let mut end = term.buffer_to_visible(span.end);
- if start > end {
- ::std::mem::swap(&mut start, &mut end);
- }
+ // Start and end lines are swapped as we switch from buffer to line coordinates
+ if start > end {
+ mem::swap(&mut start, &mut end);
+ }
- SelectionRange::new(start, end, span.is_block)
- })
+ // Trim start/end with partially visible block selection
+ start.col = max(limit_start, start.col);
+ end.col = min(limit_end, end.col);
+
+ SelectionRange::new(start.into(), end.into(), span.is_block)
});
// Load cursor glyph
@@ -1108,10 +1055,14 @@ impl Term {
Some(res)
}
- pub(crate) fn visible_to_buffer(&self, point: Point) -> Point<usize> {
+ pub fn visible_to_buffer(&self, point: Point) -> Point<usize> {
self.grid.visible_to_buffer(point)
}
+ pub fn buffer_to_visible(&self, point: impl Into<Point<usize>>) -> Point<usize> {
+ self.grid.buffer_to_visible(point)
+ }
+
/// Convert the given pixel values to a grid coordinate
///
/// The mouse coordinates are expected to be relative to the top left. The
@@ -1368,9 +1319,79 @@ impl Term {
pub fn clipboard(&mut self) -> &mut Clipboard {
&mut self.clipboard
}
+
+ pub fn urls(&self) -> Vec<Url> {
+ let display_offset = self.grid.display_offset();
+ let num_cols = self.grid.num_cols().0;
+ let last_col = Column(num_cols - 1);
+ let last_line = self.grid.num_lines() - 1;
+
+ let grid_end_point = Point::new(0, last_col);
+ let mut iter = self.grid.iter_from(grid_end_point);
+
+ let mut parser = Parser::new();
+ let mut extra_url_len = 0;
+ let mut urls = Vec::new();
+
+ let mut c = Some(iter.cell());
+ while let Some(cell) = c {
+ let point = iter.point();
+ c = iter.prev();
+
+ // Skip double-width cell but extend URL length
+ if cell.flags.contains(cell::Flags::WIDE_CHAR_SPACER) {
+ extra_url_len += 1;
+ continue;
+ }
+
+ // Interrupt URLs on line break
+ if point.col == last_col && !cell.flags.contains(cell::Flags::WRAPLINE) {
+ extra_url_len = 0;
+ parser.reset();
+ }
+
+ match parser.advance(cell.c) {
+ ParserState::Url(length) => {
+ urls.push(Url::new(point, length + extra_url_len, num_cols))
+ },
+ ParserState::NoUrl => {
+ extra_url_len = 0;
+
+ // Stop searching for URLs once the viewport has been left without active URL
+ if point.line > last_line.0 + display_offset {
+ break;
+ }
+ },
+ _ => (),
+ }
+ }
+
+ urls
+ }
+
+ pub fn url_to_string(&self, url: &Url) -> String {
+ let mut url_text = String::new();
+
+ let mut iter = self.grid.iter_from(url.start);
+
+ let mut c = Some(iter.cell());
+ while let Some(cell) = c {
+ if !cell.flags.contains(cell::Flags::WIDE_CHAR_SPACER) {
+ url_text.push(cell.c);
+ }
+
+ if iter.point() == url.end {
+ break;
+ }
+
+ c = iter.next();
+ }
+
+ url_text
+ }
}
-impl ansi::TermInfo for Term {
+impl TermInfo for Term {
#[inline]
fn lines(&self) -> Line {
self.grid.num_lines()