* basic functionality * close and reopen scratch terminal working * embed/float and resize whole tab for floating and static floating panes * move focus working * fix focus change in floating panes * move pane with mouse * floating z indices * tests and better resize algorithm * starting to work on performance * some performance experimentations * new render engine * reverse painters algorithm for floating panes * fix frame buffering * improve ux situation * handle multiple new panes on screen without overlap * adjust keybindings * adjust key hints * fix multiuser frame ui * fix various floating/multiuser bugs * remove stuff * wide characters under floating panes * fix wide character frame override * fix non-frame boundaries interactions with floating panes * fix selection character width * fix title frame wide char overflow * fix existing tests * add tests * refactor output out of tab * refactor floating panes out of tab * refactor tab * moar refactoring * refactorings and bring back terminal window title setting * add frame vte output * remove more unused stuff * remove even more unused stuff * you know the drill * refactor floating panes and remove more stuffs * refactor pane grids * remove unused output caching * refactor output * remove unused stuff * rustfmt * some formatting * rustfmt * reduce clippy to normal * remove comment * remove unused * fix closign pane * fix tests
111 lines
3.3 KiB
Rust
111 lines
3.3 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use super::LinkAnchor;
|
|
|
|
const TERMINATOR: &str = "\u{1b}\\";
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct LinkHandler {
|
|
links: HashMap<u16, Link>,
|
|
link_index: u16,
|
|
}
|
|
#[derive(Debug, Clone)]
|
|
pub struct Link {
|
|
id: Option<String>,
|
|
uri: String,
|
|
}
|
|
|
|
impl LinkHandler {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
links: HashMap::new(),
|
|
link_index: 0,
|
|
}
|
|
}
|
|
|
|
pub fn dispatch_osc8(&mut self, params: &[&[u8]]) -> Option<LinkAnchor> {
|
|
let (link_params, uri) = (params[1], params[2]);
|
|
log::debug!(
|
|
"dispatching osc8, params: {:?}, uri: {:?}",
|
|
std::str::from_utf8(link_params),
|
|
std::str::from_utf8(uri)
|
|
);
|
|
|
|
if !uri.is_empty() {
|
|
// save the link, and the id if present to hashmap
|
|
String::from_utf8(uri.to_vec()).ok().map(|uri| {
|
|
let id = link_params
|
|
.split(|&b| b == b':')
|
|
.find(|kv| kv.starts_with(b"id="))
|
|
.and_then(|kv| String::from_utf8(kv[3..].to_vec()).ok());
|
|
let anchor = LinkAnchor::Start(self.link_index);
|
|
self.links.insert(self.link_index, Link { id, uri });
|
|
self.link_index += 1;
|
|
anchor
|
|
})
|
|
} else {
|
|
// there is no link, so consider it a link end
|
|
Some(LinkAnchor::End)
|
|
}
|
|
}
|
|
|
|
pub fn output_osc8(&self, link_anchor: Option<LinkAnchor>) -> Option<String> {
|
|
link_anchor.map(|link| match link {
|
|
LinkAnchor::Start(index) => {
|
|
let link = self.links.get(&index).unwrap();
|
|
let id = link
|
|
.id
|
|
.as_ref()
|
|
.map_or("".to_string(), |id| format!("id={}", id));
|
|
format!("\u{1b}]8;{};{}{}", id, link.uri, TERMINATOR)
|
|
}
|
|
LinkAnchor::End => format!("\u{1b}]8;;{}", TERMINATOR),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Default for LinkHandler {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn dispatch_osc8_link_start() {
|
|
let mut link_handler = LinkHandler::default();
|
|
let link_params = "id=test";
|
|
let uri = "http://test.com";
|
|
let params = vec!["8".as_bytes(), link_params.as_bytes(), uri.as_bytes()];
|
|
|
|
let anchor = link_handler.dispatch_osc8(¶ms);
|
|
|
|
match anchor {
|
|
Some(LinkAnchor::Start(link_id)) => {
|
|
let link = link_handler.links.get(&link_id).expect("link was not some");
|
|
assert_eq!(link.id, Some("test".to_string()));
|
|
assert_eq!(link.uri, uri);
|
|
}
|
|
_ => panic!("pending link handler was not start"),
|
|
}
|
|
|
|
let expected = format!("\u{1b}]8;id=test;http://test.com{}", TERMINATOR);
|
|
assert_eq!(link_handler.output_osc8(anchor).unwrap(), expected);
|
|
}
|
|
|
|
#[test]
|
|
fn dispatch_osc8_link_end() {
|
|
let mut link_handler = LinkHandler::default();
|
|
let params: Vec<&[_]> = vec![b"8", b"", b""];
|
|
|
|
let anchor = link_handler.dispatch_osc8(¶ms);
|
|
|
|
assert_eq!(anchor, Some(LinkAnchor::End));
|
|
|
|
let expected = format!("\u{1b}]8;;{}", TERMINATOR);
|
|
assert_eq!(link_handler.output_osc8(anchor).unwrap(), expected);
|
|
}
|
|
}
|