mirror of
https://github.com/alacritty/alacritty.git
synced 2025-04-07 17:43:03 -04:00
parent
474d1dd6f8
commit
08da9e9b3e
1 changed files with 104 additions and 48 deletions
|
@ -9,6 +9,7 @@ use font::Metrics;
|
|||
use alacritty_terminal::index::Point;
|
||||
use alacritty_terminal::renderer::rects::{RenderLine, RenderRect};
|
||||
use alacritty_terminal::term::cell::Flags;
|
||||
use alacritty_terminal::term::color::Rgb;
|
||||
use alacritty_terminal::term::{RenderableCell, RenderableCellContent, SizeInfo};
|
||||
|
||||
use crate::config::{Config, RelaxedEq};
|
||||
|
@ -48,6 +49,7 @@ impl Url {
|
|||
pub struct Urls {
|
||||
locator: UrlLocator,
|
||||
urls: Vec<Url>,
|
||||
scheme_buffer: Vec<RenderableCell>,
|
||||
last_point: Option<Point>,
|
||||
state: UrlLocation,
|
||||
}
|
||||
|
@ -56,6 +58,7 @@ impl Default for Urls {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
locator: UrlLocator::new(),
|
||||
scheme_buffer: Vec::new(),
|
||||
urls: Vec::new(),
|
||||
state: UrlLocation::Reset,
|
||||
last_point: None,
|
||||
|
@ -82,63 +85,41 @@ impl Urls {
|
|||
};
|
||||
|
||||
let point: Point = cell.into();
|
||||
let mut end = point;
|
||||
|
||||
// Reset URL when empty cells have been skipped
|
||||
if point != Point::default() && Some(point.sub(num_cols, 1)) != self.last_point {
|
||||
self.reset();
|
||||
}
|
||||
self.last_point = Some(point);
|
||||
|
||||
// Extend by one cell for double-width characters
|
||||
if cell.flags.contains(Flags::WIDE_CHAR) {
|
||||
end.col += 1;
|
||||
}
|
||||
|
||||
self.last_point = Some(end);
|
||||
|
||||
// Advance parser
|
||||
let last_state = mem::replace(&mut self.state, self.locator.advance(c));
|
||||
match (self.state, last_state) {
|
||||
(UrlLocation::Url(_length, end_offset), _) => {
|
||||
let mut end = point;
|
||||
(UrlLocation::Url(_length, end_offset), UrlLocation::Scheme) => {
|
||||
// Create empty URL
|
||||
self.urls.push(Url { lines: Vec::new(), end_offset, num_cols });
|
||||
|
||||
// Extend by one cell for double-width characters
|
||||
if cell.flags.contains(Flags::WIDE_CHAR) {
|
||||
end.col += 1;
|
||||
|
||||
self.last_point = Some(end);
|
||||
// Push schemes into URL
|
||||
for scheme_cell in self.scheme_buffer.split_off(0) {
|
||||
let point = scheme_cell.into();
|
||||
self.extend_url(point, point, scheme_cell.fg, end_offset);
|
||||
}
|
||||
|
||||
if let Some(url) = self.urls.last_mut() {
|
||||
let last_index = url.lines.len() - 1;
|
||||
let last_line = &mut url.lines[last_index];
|
||||
|
||||
if last_line.color == cell.fg {
|
||||
// Update existing line
|
||||
last_line.end = end;
|
||||
} else {
|
||||
// Create new line with different color
|
||||
url.lines.push(RenderLine { start: point, end, color: cell.fg });
|
||||
}
|
||||
|
||||
// Update offset
|
||||
url.end_offset = end_offset;
|
||||
}
|
||||
// Push the new cell into URL
|
||||
self.extend_url(point, end, cell.fg, end_offset);
|
||||
},
|
||||
(UrlLocation::Reset, UrlLocation::Scheme) => {
|
||||
self.urls.pop();
|
||||
},
|
||||
(UrlLocation::Scheme, UrlLocation::Reset) => {
|
||||
self.urls.push(Url {
|
||||
lines: vec![RenderLine { start: point, end: point, color: cell.fg }],
|
||||
end_offset: 0,
|
||||
num_cols,
|
||||
});
|
||||
},
|
||||
(UrlLocation::Scheme, _) => {
|
||||
if let Some(url) = self.urls.last_mut() {
|
||||
if let Some(last_line) = url.lines.last_mut() {
|
||||
if last_line.color == cell.fg {
|
||||
last_line.end = point;
|
||||
} else {
|
||||
url.lines.push(RenderLine { start: point, end: point, color: cell.fg });
|
||||
}
|
||||
}
|
||||
}
|
||||
(UrlLocation::Url(_length, end_offset), UrlLocation::Url(..)) => {
|
||||
self.extend_url(point, end, cell.fg, end_offset);
|
||||
},
|
||||
(UrlLocation::Scheme, _) => self.scheme_buffer.push(cell),
|
||||
(UrlLocation::Reset, _) => self.reset(),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
@ -148,6 +129,21 @@ impl Urls {
|
|||
}
|
||||
}
|
||||
|
||||
// Extend the last URL
|
||||
fn extend_url(&mut self, start: Point, end: Point, color: Rgb, end_offset: u16) {
|
||||
let url = self.urls.last_mut().unwrap();
|
||||
|
||||
// If color changed, we need to insert a new line
|
||||
if url.lines.last().map(|last| last.color) == Some(color) {
|
||||
url.lines.last_mut().unwrap().end = end;
|
||||
} else {
|
||||
url.lines.push(RenderLine { color, start, end });
|
||||
}
|
||||
|
||||
// Update excluded cells at the end of the URL
|
||||
url.end_offset = end_offset;
|
||||
}
|
||||
|
||||
pub fn highlighted(
|
||||
&self,
|
||||
config: &Config,
|
||||
|
@ -177,12 +173,72 @@ impl Urls {
|
|||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
// Remove temporarily stored scheme URLs
|
||||
if let UrlLocation::Scheme = self.state {
|
||||
self.urls.pop();
|
||||
}
|
||||
|
||||
self.locator = UrlLocator::new();
|
||||
self.state = UrlLocation::Reset;
|
||||
self.scheme_buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
use alacritty_terminal::index::{Column, Line};
|
||||
use alacritty_terminal::term::cell::MAX_ZEROWIDTH_CHARS;
|
||||
|
||||
fn text_to_cells(text: &str) -> Vec<RenderableCell> {
|
||||
text.chars()
|
||||
.enumerate()
|
||||
.map(|(i, c)| RenderableCell {
|
||||
inner: RenderableCellContent::Chars([c; MAX_ZEROWIDTH_CHARS + 1]),
|
||||
line: Line(0),
|
||||
column: Column(i),
|
||||
fg: Default::default(),
|
||||
bg: Default::default(),
|
||||
bg_alpha: 0.,
|
||||
flags: Flags::empty(),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_color_url() {
|
||||
let mut input = text_to_cells("test https://example.org ing");
|
||||
let num_cols = input.len();
|
||||
|
||||
input[10].fg = Rgb { r: 0xff, g: 0x00, b: 0xff };
|
||||
|
||||
let mut urls = Urls::new();
|
||||
|
||||
for cell in input {
|
||||
urls.update(num_cols, cell);
|
||||
}
|
||||
|
||||
let url = urls.urls.first().unwrap();
|
||||
assert_eq!(url.start().col, Column(5));
|
||||
assert_eq!(url.end().col, Column(23));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_urls() {
|
||||
let input = text_to_cells("test git:a git:b git:c ing");
|
||||
let num_cols = input.len();
|
||||
|
||||
let mut urls = Urls::new();
|
||||
|
||||
for cell in input {
|
||||
urls.update(num_cols, cell);
|
||||
}
|
||||
|
||||
assert_eq!(urls.urls.len(), 3);
|
||||
|
||||
assert_eq!(urls.urls[0].start().col, Column(5));
|
||||
assert_eq!(urls.urls[0].end().col, Column(9));
|
||||
|
||||
assert_eq!(urls.urls[1].start().col, Column(11));
|
||||
assert_eq!(urls.urls[1].end().col, Column(15));
|
||||
|
||||
assert_eq!(urls.urls[2].start().col, Column(17));
|
||||
assert_eq!(urls.urls[2].end().col, Column(21));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue