aboutsummaryrefslogtreecommitdiff
path: root/alacritty_terminal/src/term/cell.rs
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2022-07-10 20:11:28 +0300
committerGitHub <noreply@github.com>2022-07-10 20:11:28 +0300
commit694a52bcffeffdc9e163818c3b2ac5c39e26f1ef (patch)
treea774babc1869b4c700d7df1478dbbfe5b2c3bcda /alacritty_terminal/src/term/cell.rs
parent8451b75689b44f11ec1707af7e26d915772c3972 (diff)
downloadalacritty-694a52bcffeffdc9e163818c3b2ac5c39e26f1ef.tar.gz
alacritty-694a52bcffeffdc9e163818c3b2ac5c39e26f1ef.zip
Add support for hyperlink escape sequence
This commit adds support for hyperlink escape sequence `OSC 8 ; params ; URI ST`. The configuration option responsible for those is `hints.enabled.hyperlinks`. Fixes #922.
Diffstat (limited to 'alacritty_terminal/src/term/cell.rs')
-rw-r--r--alacritty_terminal/src/term/cell.rs84
1 files changed, 79 insertions, 5 deletions
diff --git a/alacritty_terminal/src/term/cell.rs b/alacritty_terminal/src/term/cell.rs
index 716bcf9b..d3f45e9a 100644
--- a/alacritty_terminal/src/term/cell.rs
+++ b/alacritty_terminal/src/term/cell.rs
@@ -1,3 +1,4 @@
+use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use bitflags::bitflags;
@@ -33,6 +34,53 @@ bitflags! {
}
}
+/// Counter for hyperlinks without explicit ID.
+static HYPERLINK_ID_SUFFIX: AtomicU32 = AtomicU32::new(0);
+
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Hyperlink {
+ inner: Arc<HyperlinkInner>,
+}
+
+impl Hyperlink {
+ pub fn new<T: ToString>(id: Option<T>, uri: T) -> Self {
+ let inner = Arc::new(HyperlinkInner::new(id, uri));
+ Self { inner }
+ }
+
+ pub fn id(&self) -> &str {
+ &self.inner.id
+ }
+
+ pub fn uri(&self) -> &str {
+ &self.inner.uri
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
+struct HyperlinkInner {
+ /// Identifier for the given hyperlink.
+ id: String,
+
+ /// Resource identifier of the hyperlink.
+ uri: String,
+}
+
+impl HyperlinkInner {
+ pub fn new<T: ToString>(id: Option<T>, uri: T) -> Self {
+ let id = match id {
+ Some(id) => id.to_string(),
+ None => {
+ let mut id = HYPERLINK_ID_SUFFIX.fetch_add(1, Ordering::Relaxed).to_string();
+ id.push_str("_alacritty");
+ id
+ },
+ };
+
+ Self { id, uri: uri.to_string() }
+ }
+}
+
/// Trait for determining if a reset should be performed.
pub trait ResetDiscriminant<T> {
/// Value based on which equality for the reset will be determined.
@@ -61,6 +109,8 @@ pub struct CellExtra {
zerowidth: Vec<char>,
underline_color: Option<Color>,
+
+ hyperlink: Option<Hyperlink>,
}
/// Content and attributes of a single cell in the terminal grid.
@@ -113,14 +163,17 @@ impl Cell {
/// Set underline color on the cell.
pub fn set_underline_color(&mut self, color: Option<Color>) {
// If we reset color and we don't have zerowidth we should drop extra storage.
- if color.is_none() && self.extra.as_ref().map_or(true, |extra| !extra.zerowidth.is_empty())
+ if color.is_none()
+ && self
+ .extra
+ .as_ref()
+ .map_or(true, |extra| !extra.zerowidth.is_empty() || extra.hyperlink.is_some())
{
self.extra = None;
- return;
+ } else {
+ let extra = self.extra.get_or_insert(Default::default());
+ Arc::make_mut(extra).underline_color = color;
}
-
- let extra = self.extra.get_or_insert(Default::default());
- Arc::make_mut(extra).underline_color = color;
}
/// Underline color stored in this cell.
@@ -128,6 +181,27 @@ impl Cell {
pub fn underline_color(&self) -> Option<Color> {
self.extra.as_ref()?.underline_color
}
+
+ /// Set hyperlink.
+ pub fn set_hyperlink(&mut self, hyperlink: Option<Hyperlink>) {
+ let should_drop = hyperlink.is_none()
+ && self.extra.as_ref().map_or(true, |extra| {
+ !extra.zerowidth.is_empty() || extra.underline_color.is_some()
+ });
+
+ if should_drop {
+ self.extra = None;
+ } else {
+ let extra = self.extra.get_or_insert(Default::default());
+ Arc::make_mut(extra).hyperlink = hyperlink;
+ }
+ }
+
+ /// Hyperlink stored in this cell.
+ #[inline]
+ pub fn hyperlink(&self) -> Option<Hyperlink> {
+ self.extra.as_ref()?.hyperlink.clone()
+ }
}
impl GridCell for Cell {