#![cfg(test)]
use super::*;
use crate::cell::{Cell, CellAttributes};
use crate::hyperlink::{Hyperlink, Rule};
use crate::surface::line::clusterline::ClusteredLine;
use crate::surface::SEQ_ZERO;
use k9::assert_equal as assert_eq;
use std::sync::Arc;
#[test]
fn append_line() {
let mut line1: Line = "0123456789".into();
let line2: Line = "グループaa".into();
line1.append_line(line2, SEQ_ZERO);
assert_eq!(line1.len(), 20);
}
#[test]
fn hyperlinks() {
let text = "❤ 😍🤢 http://example.com \u{1f468}\u{1f3fe}\u{200d}\u{1f9b0} http://example.com";
let rules = vec![
Rule::new(r"\b\w+://(?:[\w.-]+)\.[a-z]{2,15}\S*\b", "$0").unwrap(),
Rule::new(r"\b\w+@[\w-]+(\.[\w-]+)+\b", "mailto:$0").unwrap(),
];
let hyperlink = Arc::new(Hyperlink::new_implicit("http://example.com"));
let hyperlink_attr = CellAttributes::default()
.set_hyperlink(Some(hyperlink.clone()))
.clone();
let mut line: Line = text.into();
line.scan_and_create_hyperlinks(&rules);
assert!(line.has_hyperlink());
assert_eq!(
line.coerce_vec_storage().to_vec(),
vec![
Cell::new_grapheme("❤", CellAttributes::default(), None),
Cell::new(' ', CellAttributes::default()), Cell::new_grapheme("😍", CellAttributes::default(), None),
Cell::new(' ', CellAttributes::default()), Cell::new_grapheme("🤢", CellAttributes::default(), None),
Cell::new(' ', CellAttributes::default()), Cell::new(' ', CellAttributes::default()),
Cell::new('h', hyperlink_attr.clone()),
Cell::new('t', hyperlink_attr.clone()),
Cell::new('t', hyperlink_attr.clone()),
Cell::new('p', hyperlink_attr.clone()),
Cell::new(':', hyperlink_attr.clone()),
Cell::new('/', hyperlink_attr.clone()),
Cell::new('/', hyperlink_attr.clone()),
Cell::new('e', hyperlink_attr.clone()),
Cell::new('x', hyperlink_attr.clone()),
Cell::new('a', hyperlink_attr.clone()),
Cell::new('m', hyperlink_attr.clone()),
Cell::new('p', hyperlink_attr.clone()),
Cell::new('l', hyperlink_attr.clone()),
Cell::new('e', hyperlink_attr.clone()),
Cell::new('.', hyperlink_attr.clone()),
Cell::new('c', hyperlink_attr.clone()),
Cell::new('o', hyperlink_attr.clone()),
Cell::new('m', hyperlink_attr.clone()),
Cell::new(' ', CellAttributes::default()),
Cell::new_grapheme(
"\u{1f468}\u{1f3fe}\u{200d}\u{1f9b0}",
CellAttributes::default(),
None,
),
Cell::new(' ', CellAttributes::default()), Cell::new(' ', CellAttributes::default()),
Cell::new('h', hyperlink_attr.clone()),
Cell::new('t', hyperlink_attr.clone()),
Cell::new('t', hyperlink_attr.clone()),
Cell::new('p', hyperlink_attr.clone()),
Cell::new(':', hyperlink_attr.clone()),
Cell::new('/', hyperlink_attr.clone()),
Cell::new('/', hyperlink_attr.clone()),
Cell::new('e', hyperlink_attr.clone()),
Cell::new('x', hyperlink_attr.clone()),
Cell::new('a', hyperlink_attr.clone()),
Cell::new('m', hyperlink_attr.clone()),
Cell::new('p', hyperlink_attr.clone()),
Cell::new('l', hyperlink_attr.clone()),
Cell::new('e', hyperlink_attr.clone()),
Cell::new('.', hyperlink_attr.clone()),
Cell::new('c', hyperlink_attr.clone()),
Cell::new('o', hyperlink_attr.clone()),
Cell::new('m', hyperlink_attr.clone()),
]
);
}
#[test]
fn double_click_range_bounds() {
let line: Line = "hello".into();
let r = line.compute_double_click_range(200, |_| true);
assert_eq!(r, DoubleClickRange::Range(200..200));
}
#[test]
fn cluster_representation_basic() {
let line: Line = "hello".into();
let mut compressed = line.clone();
compressed.compress_for_scrollback();
k9::snapshot!(
&compressed.cells,
r#"
C(
ClusteredLine {
text: "hello",
is_double_wide: None,
clusters: [
Cluster {
cell_width: 5,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
],
len: 5,
last_cell_width: Some(
1,
),
},
)
"#
);
compressed.coerce_vec_storage();
assert_eq!(line, compressed);
}
#[test]
fn cluster_representation_double_width() {
let line: Line = "❤ 😍🤢he❤ 😍🤢llo❤ 😍🤢".into();
let mut compressed = line.clone();
compressed.compress_for_scrollback();
k9::snapshot!(
&compressed.cells,
r#"
C(
ClusteredLine {
text: "❤ 😍🤢he❤ 😍🤢llo❤ 😍🤢",
is_double_wide: Some(
FixedBitSet {
data: [
2626580,
],
length: 23,
},
),
clusters: [
Cluster {
cell_width: 23,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
],
len: 23,
last_cell_width: Some(
1,
),
},
)
"#
);
compressed.coerce_vec_storage();
assert_eq!(line, compressed);
}
#[test]
fn cluster_representation_empty() {
let line = Line::from_cells(vec![], SEQ_ZERO);
let mut compressed = line.clone();
compressed.compress_for_scrollback();
k9::snapshot!(
&compressed.cells,
r#"
C(
ClusteredLine {
text: "",
is_double_wide: None,
clusters: [],
len: 0,
last_cell_width: None,
},
)
"#
);
compressed.coerce_vec_storage();
assert_eq!(line, compressed);
}
#[test]
fn cluster_wrap_last() {
let mut line: Line = "hello".into();
line.compress_for_scrollback();
line.set_last_cell_was_wrapped(true, 1);
k9::snapshot!(
line,
r#"
Line {
cells: C(
ClusteredLine {
text: "hello",
is_double_wide: None,
clusters: [
Cluster {
cell_width: 4,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
Cluster {
cell_width: 1,
attrs: CellAttributes {
attributes: 2048,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: true,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
],
len: 5,
last_cell_width: Some(
1,
),
},
),
zones: [],
seqno: 1,
bits: LineBits(
0x0,
),
appdata: Mutex {
data: None,
poisoned: false,
..
},
}
"#
);
}
fn bold() -> CellAttributes {
use crate::cell::Intensity;
let mut attr = CellAttributes::default();
attr.set_intensity(Intensity::Bold);
attr
}
#[test]
fn cluster_representation_attributes() {
let line = Line::from_cells(
vec![
Cell::new_grapheme("a", CellAttributes::default(), None),
Cell::new_grapheme("b", bold(), None),
Cell::new_grapheme("c", CellAttributes::default(), None),
Cell::new_grapheme("d", bold(), None),
],
SEQ_ZERO,
);
let mut compressed = line.clone();
compressed.compress_for_scrollback();
k9::snapshot!(
&compressed.cells,
r#"
C(
ClusteredLine {
text: "abcd",
is_double_wide: None,
clusters: [
Cluster {
cell_width: 1,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
Cluster {
cell_width: 1,
attrs: CellAttributes {
attributes: 1,
intensity: Bold,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
Cluster {
cell_width: 1,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
Cluster {
cell_width: 1,
attrs: CellAttributes {
attributes: 1,
intensity: Bold,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
],
len: 4,
last_cell_width: Some(
1,
),
},
)
"#
);
compressed.coerce_vec_storage();
assert_eq!(line, compressed);
}
#[test]
fn cluster_append() {
let mut cl = ClusteredLine::new();
cl.append(Cell::new_grapheme("h", CellAttributes::default(), None));
cl.append(Cell::new_grapheme("e", CellAttributes::default(), None));
cl.append(Cell::new_grapheme("l", bold(), None));
cl.append(Cell::new_grapheme("l", CellAttributes::default(), None));
cl.append(Cell::new_grapheme("o", CellAttributes::default(), None));
k9::snapshot!(
cl,
r#"
ClusteredLine {
text: "hello",
is_double_wide: None,
clusters: [
Cluster {
cell_width: 2,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
Cluster {
cell_width: 1,
attrs: CellAttributes {
attributes: 1,
intensity: Bold,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
Cluster {
cell_width: 2,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
],
len: 5,
last_cell_width: Some(
1,
),
}
"#
);
}
#[test]
fn cluster_line_new() {
let mut line = Line::new(1);
line.set_cell(
0,
Cell::new_grapheme("h", CellAttributes::default(), None),
1,
);
line.set_cell(
1,
Cell::new_grapheme("e", CellAttributes::default(), None),
2,
);
line.set_cell(2, Cell::new_grapheme("l", bold(), None), 3);
line.set_cell(
3,
Cell::new_grapheme("l", CellAttributes::default(), None),
4,
);
line.set_cell(
4,
Cell::new_grapheme("o", CellAttributes::default(), None),
5,
);
k9::snapshot!(
line,
r#"
Line {
cells: C(
ClusteredLine {
text: "hello",
is_double_wide: None,
clusters: [
Cluster {
cell_width: 2,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
Cluster {
cell_width: 1,
attrs: CellAttributes {
attributes: 1,
intensity: Bold,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
Cluster {
cell_width: 2,
attrs: CellAttributes {
attributes: 0,
intensity: Normal,
underline: None,
blink: None,
italic: false,
reverse: false,
strikethrough: false,
invisible: false,
wrapped: false,
overline: false,
semantic_type: Output,
foreground: Default,
background: Default,
fat: None,
},
},
],
len: 5,
last_cell_width: Some(
1,
),
},
),
zones: [],
seqno: 5,
bits: LineBits(
0x0,
),
appdata: Mutex {
data: None,
poisoned: false,
..
},
}
"#
);
}