zellij/zellij-server/src/panes/link_handler.rs
Aram Drevekenin 821e7cbc5a
feat(ui): add floating panes (#1066)
* 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
2022-02-18 21:10:06 +01:00

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(&params);
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(&params);
assert_eq!(anchor, Some(LinkAnchor::End));
let expected = format!("\u{1b}]8;;{}", TERMINATOR);
assert_eq!(link_handler.output_osc8(anchor).unwrap(), expected);
}
}