From 7e5f22f8c9d24119bc84aa10a9d1d7239b1f1ff1 Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Thu, 2 Nov 2023 08:17:23 +0100 Subject: [PATCH] feat(plugins): UI components (#2898) * parsing rendering private osc table * move components to DCS and add tests * refactor: move components to their own thing * ribbon and selected-ribbon ui components * nested list ui component * selected and indices for nested list * coordinates and size for ui components * use Text with ribbon * add tests for components * refactor: ui components * refactor: ui components api * style(fmt): rustfmt * style(fmt): cleanups --- src/tests/e2e/remote_runner.rs | 2 + src/tests/fixtures/nested-list-ui-component | 1 + .../nested-list-ui-component-with-coordinates | 1 + src/tests/fixtures/ribbon-ui-component | 1 + .../ribbon-ui-component-with-coordinates | 1 + src/tests/fixtures/table-ui-component | 1 + .../table-ui-component-with-coordinates | 1 + src/tests/fixtures/text-ui-component | 1 + .../text-ui-component-with-coordinates | 1 + zellij-server/src/panes/grid.rs | 21 + zellij-server/src/panes/plugin_pane.rs | 5 + zellij-server/src/panes/terminal_pane.rs | 5 + zellij-server/src/panes/unit/grid_tests.rs | 529 +++++++++++++++++- .../src/panes/unit/search_in_pane_tests.rs | 2 + ..._grid_tests__nested_list_ui_component.snap | 47 ++ ...ed_list_ui_component_with_coordinates.snap | 47 ++ ...d_tests__ribbon_selected_ui_component.snap | 47 ++ ...grid__grid_tests__ribbon_ui_component.snap | 47 ++ ..._ribbon_ui_component_with_coordinates.snap | 47 ++ ..._grid__grid_tests__table_ui_component.snap | 47 ++ ...__table_ui_component_with_coordinates.snap | 47 ++ ...__grid__grid_tests__text_ui_component.snap | 47 ++ ...s__text_ui_component_with_coordinates.snap | 47 ++ .../src/panes/unit/terminal_pane_tests.rs | 24 + zellij-server/src/screen.rs | 10 +- zellij-server/src/tab/layout_applier.rs | 7 + zellij-server/src/tab/mod.rs | 13 + .../src/tab/unit/tab_integration_tests.rs | 21 + zellij-server/src/tab/unit/tab_tests.rs | 6 + .../ui/components/component_coordinates.rs | 43 ++ zellij-server/src/ui/components/mod.rs | 187 +++++++ .../src/ui/components/nested_list.rs | 142 +++++ zellij-server/src/ui/components/ribbon.rs | 115 ++++ zellij-server/src/ui/components/table.rs | 105 ++++ zellij-server/src/ui/components/text.rs | 166 ++++++ zellij-server/src/ui/mod.rs | 1 + zellij-server/src/unit/screen_tests.rs | 7 +- zellij-tile/src/lib.rs | 1 + zellij-tile/src/shim.rs | 1 + zellij-tile/src/ui_components/mod.rs | 12 + zellij-tile/src/ui_components/nested_list.rs | 73 +++ zellij-tile/src/ui_components/ribbon.rs | 24 + zellij-tile/src/ui_components/table.rs | 61 ++ zellij-tile/src/ui_components/text.rs | 107 ++++ 44 files changed, 2117 insertions(+), 4 deletions(-) create mode 100644 src/tests/fixtures/nested-list-ui-component create mode 100644 src/tests/fixtures/nested-list-ui-component-with-coordinates create mode 100644 src/tests/fixtures/ribbon-ui-component create mode 100644 src/tests/fixtures/ribbon-ui-component-with-coordinates create mode 100644 src/tests/fixtures/table-ui-component create mode 100644 src/tests/fixtures/table-ui-component-with-coordinates create mode 100644 src/tests/fixtures/text-ui-component create mode 100644 src/tests/fixtures/text-ui-component-with-coordinates create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__nested_list_ui_component.snap create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__nested_list_ui_component_with_coordinates.snap create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_selected_ui_component.snap create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_ui_component.snap create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_ui_component_with_coordinates.snap create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component.snap create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component_with_coordinates.snap create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__text_ui_component.snap create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__text_ui_component_with_coordinates.snap create mode 100644 zellij-server/src/ui/components/component_coordinates.rs create mode 100644 zellij-server/src/ui/components/mod.rs create mode 100644 zellij-server/src/ui/components/nested_list.rs create mode 100644 zellij-server/src/ui/components/ribbon.rs create mode 100644 zellij-server/src/ui/components/table.rs create mode 100644 zellij-server/src/ui/components/text.rs create mode 100644 zellij-tile/src/ui_components/mod.rs create mode 100644 zellij-tile/src/ui_components/nested_list.rs create mode 100644 zellij-tile/src/ui_components/ribbon.rs create mode 100644 zellij-tile/src/ui_components/table.rs create mode 100644 zellij-tile/src/ui_components/text.rs diff --git a/src/tests/e2e/remote_runner.rs b/src/tests/e2e/remote_runner.rs index 0da5bce7..60a3eb56 100644 --- a/src/tests/e2e/remote_runner.rs +++ b/src/tests/e2e/remote_runner.rs @@ -235,6 +235,7 @@ fn read_from_channel( }))); let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let debug = false; + let arrow_fonts = true; let mut terminal_output = TerminalPane::new( 0, pane_geom, @@ -249,6 +250,7 @@ fn read_from_channel( None, None, debug, + arrow_fonts, ); // 0 is the pane index loop { if !should_keep_running.load(Ordering::SeqCst) { diff --git a/src/tests/fixtures/nested-list-ui-component b/src/tests/fixtures/nested-list-ui-component new file mode 100644 index 00000000..fd1b4e08 --- /dev/null +++ b/src/tests/fixtures/nested-list-ui-component @@ -0,0 +1 @@ +Pznested_list;105,116,101,109,32,49;105,116,101,109,32,50;|105,116,101,109,32,51;105,116,101,109,32,52;|105,116,101,109,32,53,32,108,115,100,107,102,106,108,115,107,100,106,32,102,108,107,115,100,106,102,32,108,107,115,100,106,32,102,108,107,115,106,100,32,102;||105,116,101,109,32,54,32,115,108,100,107,102,106,115,108,107,100,102,106,32,108,115,100,107,106,102,32,108,115,107,100,106,102,32,108,115,107,100,106,102,32,108,107,115,100,106,102,32,108,115,107,100,106,102,32;105,116,101,109,32,55\ diff --git a/src/tests/fixtures/nested-list-ui-component-with-coordinates b/src/tests/fixtures/nested-list-ui-component-with-coordinates new file mode 100644 index 00000000..73a677d9 --- /dev/null +++ b/src/tests/fixtures/nested-list-ui-component-with-coordinates @@ -0,0 +1 @@ +Pznested_list;1/1/20/3;$0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,8$$10,11,12,13,14,15,16,17,18,19,20,21,22,23,24$105,116,101,109,32,49,32,119,105,116,104,32,115,111,109,101,32,110,105,99,101,32,116,101,120,116,46,46,46;|$8$0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32$1,2,3,4,5,6,7,8,9,10,11,12,13,14$105,116,101,109,32,50,32,119,105,116,104,32,115,111,109,101,32,110,111,116,32,115,111,32,110,105,99,101,32,116,101,120,116;x$0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,8$$5,6,7,8,9,10,11,12,13,14,15,16,17,18,19$105,116,101,109,32,51,32,105,115,32,97,32,114,101,97,108,32,101,121,101,32,111,112,101,110,101,114;|$8$$0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1,2,3,4,5,6,7,8,9,10,11,12,13,14$105,116,101,109,32,52,32,105,115,32,106,117,115,116,32,97,110,111,116,104,101,114,32,105,116,101,109,44,32,114,101,97,108,108,121\ diff --git a/src/tests/fixtures/ribbon-ui-component b/src/tests/fixtures/ribbon-ui-component new file mode 100644 index 00000000..5e28ccdd --- /dev/null +++ b/src/tests/fixtures/ribbon-ui-component @@ -0,0 +1 @@ +Pzribbon;27,91,49,109,60,27,91,51,56,59,53,59,57,109,110,27,91,51,57,59,51,56,59,53,59,48,109,62,32,82,69,83,73,90,69\ diff --git a/src/tests/fixtures/ribbon-ui-component-with-coordinates b/src/tests/fixtures/ribbon-ui-component-with-coordinates new file mode 100644 index 00000000..d3c33ad3 --- /dev/null +++ b/src/tests/fixtures/ribbon-ui-component-with-coordinates @@ -0,0 +1 @@ +Pzribbon;2/2/10/;1,2,3,4$114,105,98,98,111,110,32,49\ diff --git a/src/tests/fixtures/table-ui-component b/src/tests/fixtures/table-ui-component new file mode 100644 index 00000000..60754bbb --- /dev/null +++ b/src/tests/fixtures/table-ui-component @@ -0,0 +1 @@ +Pztable;5;7;116,105,116,108,101,49;116,105,116,108,101,50;116,105,116,108,101,51;116,105,116,108,101,52;116,105,116,108,101,53;49,108,107,115,100,106,102,108,107,115,100,106,102;108,107,106,100,115,102,108,107,115,106,100,102;108,107,106,115,100,108,107,102,106,115,102,100;108,107,106,115,100,108,107,106,102,100;108,107,106,100,115,108,107,106,115,100,102;50,108,107,115,100,106,102,108,107,115,100,106,102;108,107,106,100,115,102,108,107,115,106,100,102;108,107,106,240,159,152,179,240,159,152,179,115,100,108,107,102,106,115,102,100;108,107,106,115,100,108,107,106,102,100;108,107,106,100,115,108,107,106,115,100,102;51,108,107,115,100,106,102,108,107,115,100,106,102;108,107,106,100,115,102,108,107,115,106,100,102;108,107,106,115,100,240,159,152,179,108,107,102,106,115,102,100;108,107,106,115,100,108,107,106,102,100;108,107,106,100,115,108,107,106,115,100,102;52,108,107,115,100,106,102,108,107,115,50,50,50,100,106,102;108,107,240,159,152,179,50,50,50,106,100,115,102,108,107,115,106,100,102;108,107,50,50,50,106,115,100,108,107,102,106,115,102,100;108,107,119,119,119,106,115,100,108,107,106,102,100;108,107,106,100,115,108,107,106,115,100,102;53,108,107,115,100,106,102,108,107,115,100,106,102;108,107,106,100,115,102,108,107,115,106,100,102;108,107,106,115,100,108,107,102,106,115,102,100;108,107,115,100,106,102,108,107,115,106,102,100,108,107,106,115,100,108,107,106,102,100;108,107,106,100,114,114,114,114,115,108,107,106,115,100,102;27,91,51,54,109,54,108,107,115,100,106,102,108,107,240,159,152,179,115,100,106,102;27,91,52,54,109,108,240,159,152,179,107,106,100,115,102,108,107,115,106,100,102;108,107,106,115,100,108,107,102,106,115,102,100;108,107,106,115,100,108,107,106,102,100;108,119,119,107,119,107,106,100,115,108,107,106,115,100,102\ diff --git a/src/tests/fixtures/table-ui-component-with-coordinates b/src/tests/fixtures/table-ui-component-with-coordinates new file mode 100644 index 00000000..927237e9 --- /dev/null +++ b/src/tests/fixtures/table-ui-component-with-coordinates @@ -0,0 +1 @@ +Pztable;4/4/20/3;3;5;116,105,116,108,101,49;116,105,116,108,101,50;116,105,116,108,101,51;1,2,3,4$99,111,110,116,101,110,116,32,49;$$0,1,2,3,4,5,6,7,8$99,111,110,116,101,110,116,32,50;99,111,110,116,101,110,116,32,51;x99,111,110,116,101,110,116,32,49,49;x99,111,110,116,101,110,116,32,50,50;x99,111,110,116,101,110,116,32,51,51;99,111,110,116,101,110,116,32,49,49,49;99,111,110,116,101,110,116,32,50,50,50;99,111,110,116,101,110,116,32,51,51;99,111,110,116,101,110,116,32,49,49;x99,111,110,116,101,110,116,32,50,50;99,111,110,116,101,110,116,32,51,51\ diff --git a/src/tests/fixtures/text-ui-component b/src/tests/fixtures/text-ui-component new file mode 100644 index 00000000..348f405b --- /dev/null +++ b/src/tests/fixtures/text-ui-component @@ -0,0 +1 @@ +Pztext;x0,1,2$3,4,5$7,8,9$102,111,111,32,98,97,114,32,98,97,122\ diff --git a/src/tests/fixtures/text-ui-component-with-coordinates b/src/tests/fixtures/text-ui-component-with-coordinates new file mode 100644 index 00000000..aeb7867e --- /dev/null +++ b/src/tests/fixtures/text-ui-component-with-coordinates @@ -0,0 +1 @@ +Pztext;58/4//;x0,1,2$3,4,5$7,8,9$102,111,111,32,98,97,114,32,98,97,122\ diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index c902e23a..5ee8928d 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -38,6 +38,7 @@ use crate::panes::terminal_character::{ AnsiCode, CharacterStyles, CharsetIndex, Cursor, CursorShape, StandardCharset, TerminalCharacter, EMPTY_TERMINAL_CHARACTER, }; +use crate::ui::components::UiComponentParser; fn get_top_non_canonical_rows(rows: &mut Vec) -> Vec { let mut index_of_last_non_canonical_row = None; @@ -369,7 +370,10 @@ pub struct Grid { pub focus_event_tracking: bool, pub search_results: SearchResult, pub pending_clipboard_update: Option, + ui_component_bytes: Option>, + style: Style, debug: bool, + arrow_fonts: bool, } #[derive(Clone, Debug)] @@ -457,7 +461,9 @@ impl Grid { link_handler: Rc>, character_cell_size: Rc>>, sixel_image_store: Rc>, + style: Style, // TODO: consolidate this with terminal_emulator_colors debug: bool, + arrow_fonts: bool, ) -> Self { let sixel_grid = SixelGrid::new(character_cell_size.clone(), sixel_image_store); // make sure this is initialized as it is used internally @@ -507,7 +513,10 @@ impl Grid { search_results: Default::default(), sixel_grid, pending_clipboard_update: None, + ui_component_bytes: None, + style, debug, + arrow_fonts, } } pub fn render_full_viewport(&mut self) { @@ -2196,6 +2205,9 @@ impl Perform for Grid { params.iter().collect(), ); } + } else if c == 'z' { + // UI-component (Zellij internal) + self.ui_component_bytes = Some(vec![]); } } @@ -2205,12 +2217,21 @@ impl Perform for Grid { // we explicitly set this to false here because in the context of Sixel, we only render the // image when it's done, i.e. in the unhook method self.should_render = false; + } else if let Some(ui_component_bytes) = self.ui_component_bytes.as_mut() { + ui_component_bytes.push(byte); } } fn unhook(&mut self) { if self.sixel_grid.is_parsing() { self.create_sixel_image(); + } else if let Some(mut ui_component_bytes) = self.ui_component_bytes.take() { + let component_bytes = ui_component_bytes.drain(..); + let style = self.style.clone(); + let arrow_fonts = self.arrow_fonts; + UiComponentParser::new(self, style, arrow_fonts) + .parse(component_bytes.collect()) + .non_fatal(); } self.mark_for_rerender(); } diff --git a/zellij-server/src/panes/plugin_pane.rs b/zellij-server/src/panes/plugin_pane.rs index 43f9c39c..5c4c4f08 100644 --- a/zellij-server/src/panes/plugin_pane.rs +++ b/zellij-server/src/panes/plugin_pane.rs @@ -49,7 +49,9 @@ macro_rules! get_or_create_grid { $self.link_handler.clone(), $self.character_cell_size.clone(), $self.sixel_image_store.clone(), + $self.style.clone(), $self.debug, + $self.arrow_fonts, ); grid.hide_cursor(); grid @@ -85,6 +87,7 @@ pub(crate) struct PluginPane { loading_indication: LoadingIndication, requesting_permissions: Option, debug: bool, + arrow_fonts: bool, } impl PluginPane { @@ -103,6 +106,7 @@ impl PluginPane { style: Style, invoked_with: Option, debug: bool, + arrow_fonts: bool, ) -> Self { let loading_indication = LoadingIndication::new(title.clone()).with_colors(style.colors); let initial_loading_message = loading_indication.to_string(); @@ -134,6 +138,7 @@ impl PluginPane { loading_indication, requesting_permissions: None, debug, + arrow_fonts, }; for client_id in currently_connected_clients { plugin.handle_plugin_bytes(client_id, initial_loading_message.as_bytes().to_vec()); diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs index ac4c6da6..b6a03fcf 100644 --- a/zellij-server/src/panes/terminal_pane.rs +++ b/zellij-server/src/panes/terminal_pane.rs @@ -115,6 +115,7 @@ pub struct TerminalPane { // held on startup and can possibly be used to display some errors pane_frame_color_override: Option<(PaletteColor, Option)>, invoked_with: Option, + arrow_fonts: bool, } impl Pane for TerminalPane { @@ -786,6 +787,7 @@ impl TerminalPane { initial_pane_title: Option, invoked_with: Option, debug: bool, + arrow_fonts: bool, ) -> TerminalPane { let initial_pane_title = initial_pane_title.unwrap_or_else(|| format!("Pane #{}", pane_index)); @@ -797,7 +799,9 @@ impl TerminalPane { link_handler, character_cell_size, sixel_image_store, + style.clone(), debug, + arrow_fonts, ); TerminalPane { frame: HashMap::new(), @@ -822,6 +826,7 @@ impl TerminalPane { banner: None, pane_frame_color_override: None, invoked_with, + arrow_fonts, } } pub fn get_x(&self) -> usize { diff --git a/zellij-server/src/panes/unit/grid_tests.rs b/zellij-server/src/panes/unit/grid_tests.rs index 3b186474..23181c5f 100644 --- a/zellij-server/src/panes/unit/grid_tests.rs +++ b/zellij-server/src/panes/unit/grid_tests.rs @@ -5,7 +5,12 @@ use ::insta::assert_snapshot; use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -use zellij_utils::{data::Palette, pane_size::SizeInPixels, position::Position, vte}; +use zellij_utils::{ + data::{Palette, Style}, + pane_size::SizeInPixels, + position::Position, + vte, +}; use std::fmt::Write; @@ -25,6 +30,7 @@ fn vttest1_0() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -33,7 +39,9 @@ fn vttest1_0() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest1-0"; let content = read_fixture(fixture_name); @@ -49,6 +57,7 @@ fn vttest1_1() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -57,7 +66,9 @@ fn vttest1_1() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest1-1"; let content = read_fixture(fixture_name); @@ -73,6 +84,7 @@ fn vttest1_2() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -81,7 +93,9 @@ fn vttest1_2() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest1-2"; let content = read_fixture(fixture_name); @@ -97,6 +111,7 @@ fn vttest1_3() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -105,7 +120,9 @@ fn vttest1_3() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest1-3"; let content = read_fixture(fixture_name); @@ -121,6 +138,7 @@ fn vttest1_4() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -129,7 +147,9 @@ fn vttest1_4() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest1-4"; let content = read_fixture(fixture_name); @@ -145,6 +165,7 @@ fn vttest1_5() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -153,7 +174,9 @@ fn vttest1_5() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest1-5"; let content = read_fixture(fixture_name); @@ -169,6 +192,7 @@ fn vttest2_0() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -177,7 +201,9 @@ fn vttest2_0() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-0"; let content = read_fixture(fixture_name); @@ -193,6 +219,7 @@ fn vttest2_1() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -201,7 +228,9 @@ fn vttest2_1() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-1"; let content = read_fixture(fixture_name); @@ -217,6 +246,7 @@ fn vttest2_2() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -225,7 +255,9 @@ fn vttest2_2() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-2"; let content = read_fixture(fixture_name); @@ -241,6 +273,7 @@ fn vttest2_3() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -249,7 +282,9 @@ fn vttest2_3() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-3"; let content = read_fixture(fixture_name); @@ -265,6 +300,7 @@ fn vttest2_4() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -273,7 +309,9 @@ fn vttest2_4() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-4"; let content = read_fixture(fixture_name); @@ -289,6 +327,7 @@ fn vttest2_5() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -297,7 +336,9 @@ fn vttest2_5() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-5"; let content = read_fixture(fixture_name); @@ -313,6 +354,7 @@ fn vttest2_6() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -321,7 +363,9 @@ fn vttest2_6() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-6"; let content = read_fixture(fixture_name); @@ -337,6 +381,7 @@ fn vttest2_7() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -345,7 +390,9 @@ fn vttest2_7() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-7"; let content = read_fixture(fixture_name); @@ -361,6 +408,7 @@ fn vttest2_8() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -369,7 +417,9 @@ fn vttest2_8() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-8"; let content = read_fixture(fixture_name); @@ -385,6 +435,7 @@ fn vttest2_9() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -393,7 +444,9 @@ fn vttest2_9() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-9"; let content = read_fixture(fixture_name); @@ -409,6 +462,7 @@ fn vttest2_10() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -417,7 +471,9 @@ fn vttest2_10() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-10"; let content = read_fixture(fixture_name); @@ -433,6 +489,7 @@ fn vttest2_11() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -441,7 +498,9 @@ fn vttest2_11() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-11"; let content = read_fixture(fixture_name); @@ -457,6 +516,7 @@ fn vttest2_12() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -465,7 +525,9 @@ fn vttest2_12() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-12"; let content = read_fixture(fixture_name); @@ -481,6 +543,7 @@ fn vttest2_13() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -489,7 +552,9 @@ fn vttest2_13() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-13"; let content = read_fixture(fixture_name); @@ -505,6 +570,7 @@ fn vttest2_14() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -513,7 +579,9 @@ fn vttest2_14() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest2-14"; let content = read_fixture(fixture_name); @@ -529,6 +597,7 @@ fn vttest3_0() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 41, 110, @@ -537,7 +606,9 @@ fn vttest3_0() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest3-0"; let content = read_fixture(fixture_name); @@ -553,6 +624,7 @@ fn vttest8_0() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -561,7 +633,9 @@ fn vttest8_0() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest8-0"; let content = read_fixture(fixture_name); @@ -577,6 +651,7 @@ fn vttest8_1() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -585,7 +660,9 @@ fn vttest8_1() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest8-1"; let content = read_fixture(fixture_name); @@ -601,6 +678,7 @@ fn vttest8_2() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -609,7 +687,9 @@ fn vttest8_2() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest8-2"; let content = read_fixture(fixture_name); @@ -625,6 +705,7 @@ fn vttest8_3() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -633,7 +714,9 @@ fn vttest8_3() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest8-3"; let content = read_fixture(fixture_name); @@ -649,6 +732,7 @@ fn vttest8_4() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -657,7 +741,9 @@ fn vttest8_4() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest8-4"; let content = read_fixture(fixture_name); @@ -673,6 +759,7 @@ fn vttest8_5() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -681,7 +768,9 @@ fn vttest8_5() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vttest8-5"; let content = read_fixture(fixture_name); @@ -697,6 +786,7 @@ fn csi_b() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -705,7 +795,9 @@ fn csi_b() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "csi-b"; let content = read_fixture(fixture_name); @@ -721,6 +813,7 @@ fn csi_capital_i() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -729,7 +822,9 @@ fn csi_capital_i() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "csi-capital-i"; let content = read_fixture(fixture_name); @@ -745,6 +840,7 @@ fn csi_capital_z() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -753,7 +849,9 @@ fn csi_capital_z() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "csi-capital-z"; let content = read_fixture(fixture_name); @@ -769,6 +867,7 @@ fn terminal_reports() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -777,7 +876,9 @@ fn terminal_reports() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "terminal_reports"; let content = read_fixture(fixture_name); @@ -793,6 +894,7 @@ fn wide_characters() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -801,7 +903,9 @@ fn wide_characters() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide_characters"; let content = read_fixture(fixture_name); @@ -817,6 +921,7 @@ fn wide_characters_line_wrap() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -825,7 +930,9 @@ fn wide_characters_line_wrap() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide_characters_line_wrap"; let content = read_fixture(fixture_name); @@ -841,6 +948,7 @@ fn insert_character_in_line_with_wide_character() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -849,7 +957,9 @@ fn insert_character_in_line_with_wide_character() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide_characters_middle_line_insert"; let content = read_fixture(fixture_name); @@ -865,6 +975,7 @@ fn delete_char_in_middle_of_line_with_widechar() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -873,7 +984,9 @@ fn delete_char_in_middle_of_line_with_widechar() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide-chars-delete-middle"; let content = read_fixture(fixture_name); @@ -889,6 +1002,7 @@ fn delete_char_in_middle_of_line_with_multiple_widechars() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -897,7 +1011,9 @@ fn delete_char_in_middle_of_line_with_multiple_widechars() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide-chars-delete-middle-after-multi"; let content = read_fixture(fixture_name); @@ -913,6 +1029,7 @@ fn fish_wide_characters_override_clock() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -921,7 +1038,9 @@ fn fish_wide_characters_override_clock() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "fish_wide_characters_override_clock"; let content = read_fixture(fixture_name); @@ -937,6 +1056,7 @@ fn bash_delete_wide_characters() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -945,7 +1065,9 @@ fn bash_delete_wide_characters() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "bash_delete_wide_characters"; let content = read_fixture(fixture_name); @@ -961,6 +1083,7 @@ fn delete_wide_characters_before_cursor() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -969,7 +1092,9 @@ fn delete_wide_characters_before_cursor() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "delete_wide_characters_before_cursor"; let content = read_fixture(fixture_name); @@ -985,6 +1110,7 @@ fn delete_wide_characters_before_cursor_when_cursor_is_on_wide_character() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -993,7 +1119,9 @@ fn delete_wide_characters_before_cursor_when_cursor_is_on_wide_character() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "delete_wide_characters_before_cursor_when_cursor_is_on_wide_character"; let content = read_fixture(fixture_name); @@ -1009,6 +1137,7 @@ fn delete_wide_character_under_cursor() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -1017,7 +1146,9 @@ fn delete_wide_character_under_cursor() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "delete_wide_character_under_cursor"; let content = read_fixture(fixture_name); @@ -1033,6 +1164,7 @@ fn replace_wide_character_under_cursor() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 104, @@ -1041,7 +1173,9 @@ fn replace_wide_character_under_cursor() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "replace_wide_character_under_cursor"; let content = read_fixture(fixture_name); @@ -1057,6 +1191,7 @@ fn wrap_wide_characters() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 90, @@ -1065,7 +1200,9 @@ fn wrap_wide_characters() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide_characters_full"; let content = read_fixture(fixture_name); @@ -1081,6 +1218,7 @@ fn wrap_wide_characters_on_size_change() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 93, @@ -1089,7 +1227,9 @@ fn wrap_wide_characters_on_size_change() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide_characters_full"; let content = read_fixture(fixture_name); @@ -1106,6 +1246,7 @@ fn unwrap_wide_characters_on_size_change() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 93, @@ -1114,7 +1255,9 @@ fn unwrap_wide_characters_on_size_change() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide_characters_full"; let content = read_fixture(fixture_name); @@ -1132,6 +1275,7 @@ fn wrap_wide_characters_in_the_middle_of_the_line() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 91, @@ -1140,7 +1284,9 @@ fn wrap_wide_characters_in_the_middle_of_the_line() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide_characters_line_middle"; let content = read_fixture(fixture_name); @@ -1156,6 +1302,7 @@ fn wrap_wide_characters_at_the_end_of_the_line() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 90, @@ -1164,7 +1311,9 @@ fn wrap_wide_characters_at_the_end_of_the_line() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "wide_characters_line_end"; let content = read_fixture(fixture_name); @@ -1180,6 +1329,7 @@ fn copy_selected_text_from_viewport() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 27, 125, @@ -1188,7 +1338,9 @@ fn copy_selected_text_from_viewport() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "grid_copy"; let content = read_fixture(fixture_name); @@ -1212,6 +1364,7 @@ fn copy_wrapped_selected_text_from_viewport() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 22, 73, @@ -1220,7 +1373,9 @@ fn copy_wrapped_selected_text_from_viewport() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "grid_copy_wrapped"; let content = read_fixture(fixture_name); @@ -1243,6 +1398,7 @@ fn copy_selected_text_from_lines_above() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 27, 125, @@ -1251,7 +1407,9 @@ fn copy_selected_text_from_lines_above() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "grid_copy"; let content = read_fixture(fixture_name); @@ -1275,6 +1433,7 @@ fn copy_selected_text_from_lines_below() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 27, 125, @@ -1283,7 +1442,9 @@ fn copy_selected_text_from_lines_below() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "grid_copy"; let content = read_fixture(fixture_name); @@ -1315,6 +1476,7 @@ fn run_bandwhich_from_fish_shell() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1323,7 +1485,9 @@ fn run_bandwhich_from_fish_shell() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "fish_and_bandwhich"; let content = read_fixture(fixture_name); @@ -1339,6 +1503,7 @@ fn fish_tab_completion_options() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1347,7 +1512,9 @@ fn fish_tab_completion_options() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "fish_tab_completion_options"; let content = read_fixture(fixture_name); @@ -1369,6 +1536,7 @@ pub fn fish_select_tab_completion_options() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1377,7 +1545,9 @@ pub fn fish_select_tab_completion_options() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "fish_select_tab_completion_options"; let content = read_fixture(fixture_name); @@ -1403,6 +1573,7 @@ pub fn vim_scroll_region_down() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1411,7 +1582,9 @@ pub fn vim_scroll_region_down() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vim_scroll_region_down"; let content = read_fixture(fixture_name); @@ -1434,6 +1607,7 @@ pub fn vim_ctrl_d() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1442,7 +1616,9 @@ pub fn vim_ctrl_d() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vim_ctrl_d"; let content = read_fixture(fixture_name); @@ -1464,6 +1640,7 @@ pub fn vim_ctrl_u() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1472,7 +1649,9 @@ pub fn vim_ctrl_u() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vim_ctrl_u"; let content = read_fixture(fixture_name); @@ -1488,6 +1667,7 @@ pub fn htop() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1496,7 +1676,9 @@ pub fn htop() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "htop"; let content = read_fixture(fixture_name); @@ -1512,6 +1694,7 @@ pub fn htop_scrolling() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1520,7 +1703,9 @@ pub fn htop_scrolling() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "htop_scrolling"; let content = read_fixture(fixture_name); @@ -1536,6 +1721,7 @@ pub fn htop_right_scrolling() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1544,7 +1730,9 @@ pub fn htop_right_scrolling() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "htop_right_scrolling"; let content = read_fixture(fixture_name); @@ -1570,6 +1758,7 @@ pub fn vim_overwrite() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1578,7 +1767,9 @@ pub fn vim_overwrite() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "vim_overwrite"; let content = read_fixture(fixture_name); @@ -1596,6 +1787,7 @@ pub fn clear_scroll_region() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1604,7 +1796,9 @@ pub fn clear_scroll_region() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "clear_scroll_region"; let content = read_fixture(fixture_name); @@ -1620,6 +1814,7 @@ pub fn display_tab_characters_properly() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1628,7 +1823,9 @@ pub fn display_tab_characters_properly() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "tab_characters"; let content = read_fixture(fixture_name); @@ -1644,6 +1841,7 @@ pub fn neovim_insert_mode() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1652,7 +1850,9 @@ pub fn neovim_insert_mode() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "nvim_insert"; let content = read_fixture(fixture_name); @@ -1668,6 +1868,7 @@ pub fn bash_cursor_linewrap() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 116, @@ -1676,7 +1877,9 @@ pub fn bash_cursor_linewrap() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "bash_cursor_linewrap"; let content = read_fixture(fixture_name); @@ -1694,6 +1897,7 @@ pub fn fish_paste_multiline() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 149, @@ -1702,7 +1906,9 @@ pub fn fish_paste_multiline() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "fish_paste_multiline"; let content = read_fixture(fixture_name); @@ -1718,6 +1924,7 @@ pub fn git_log() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 149, @@ -1726,7 +1933,9 @@ pub fn git_log() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "git_log"; let content = read_fixture(fixture_name); @@ -1744,6 +1953,7 @@ pub fn git_diff_scrollup() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 28, 149, @@ -1752,7 +1962,9 @@ pub fn git_diff_scrollup() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "git_diff_scrollup"; let content = read_fixture(fixture_name); @@ -1768,6 +1980,7 @@ pub fn emacs_longbuf() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 60, 284, @@ -1776,7 +1989,9 @@ pub fn emacs_longbuf() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "emacs_longbuf_tutorial"; let content = read_fixture(fixture_name); @@ -1792,6 +2007,7 @@ pub fn top_and_quit() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 56, 235, @@ -1800,7 +2016,9 @@ pub fn top_and_quit() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "top_and_quit"; let content = read_fixture(fixture_name); @@ -1823,6 +2041,7 @@ pub fn exa_plus_omf_theme() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 56, 235, @@ -1831,7 +2050,9 @@ pub fn exa_plus_omf_theme() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "exa_plus_omf_theme"; let content = read_fixture(fixture_name); @@ -1847,6 +2068,7 @@ pub fn scroll_up() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 10, 50, @@ -1855,7 +2077,9 @@ pub fn scroll_up() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "scrolling"; let content = read_fixture(fixture_name); @@ -1872,6 +2096,7 @@ pub fn scroll_down() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 10, 50, @@ -1880,7 +2105,9 @@ pub fn scroll_down() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "scrolling"; let content = read_fixture(fixture_name); @@ -1898,6 +2125,7 @@ pub fn scroll_up_with_line_wraps() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 10, 25, @@ -1906,7 +2134,9 @@ pub fn scroll_up_with_line_wraps() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "scrolling"; let content = read_fixture(fixture_name); @@ -1923,6 +2153,7 @@ pub fn scroll_down_with_line_wraps() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 10, 25, @@ -1931,7 +2162,9 @@ pub fn scroll_down_with_line_wraps() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "scrolling"; let content = read_fixture(fixture_name); @@ -1949,6 +2182,7 @@ pub fn scroll_up_decrease_width_and_scroll_down() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 10, 50, @@ -1957,7 +2191,9 @@ pub fn scroll_up_decrease_width_and_scroll_down() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "scrolling"; let content = read_fixture(fixture_name); @@ -1980,6 +2216,7 @@ pub fn scroll_up_increase_width_and_scroll_down() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 10, 25, @@ -1988,7 +2225,9 @@ pub fn scroll_up_increase_width_and_scroll_down() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "scrolling"; let content = read_fixture(fixture_name); @@ -2011,6 +2250,7 @@ pub fn move_cursor_below_scroll_region() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 34, 114, @@ -2019,7 +2259,9 @@ pub fn move_cursor_below_scroll_region() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "move_cursor_below_scroll_region"; let content = read_fixture(fixture_name); @@ -2035,6 +2277,7 @@ pub fn insert_wide_characters_in_existing_line() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 21, 86, @@ -2043,7 +2286,9 @@ pub fn insert_wide_characters_in_existing_line() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "chinese_characters_line_middle"; let content = read_fixture(fixture_name); @@ -2065,6 +2310,7 @@ pub fn full_screen_scroll_region_and_scroll_up() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 54, 80, @@ -2073,7 +2319,9 @@ pub fn full_screen_scroll_region_and_scroll_up() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "scroll_region_full_screen"; let content = read_fixture(fixture_name); @@ -2092,6 +2340,7 @@ pub fn ring_bell() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 134, 64, @@ -2100,7 +2349,9 @@ pub fn ring_bell() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "ring_bell"; let content = read_fixture(fixture_name); @@ -2116,6 +2367,7 @@ pub fn alternate_screen_change_size() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 20, 20, @@ -2124,7 +2376,9 @@ pub fn alternate_screen_change_size() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "alternate_screen_change_size"; let content = read_fixture(fixture_name); @@ -2144,6 +2398,7 @@ pub fn fzf_fullscreen() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2152,7 +2407,9 @@ pub fn fzf_fullscreen() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "fzf_fullscreen"; let content = read_fixture(fixture_name); @@ -2172,6 +2429,7 @@ pub fn replace_multiple_wide_characters_under_cursor() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2180,7 +2438,9 @@ pub fn replace_multiple_wide_characters_under_cursor() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "replace_multiple_wide_characters"; let content = read_fixture(fixture_name); @@ -2200,6 +2460,7 @@ pub fn replace_non_wide_characters_with_wide_characters() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2208,7 +2469,9 @@ pub fn replace_non_wide_characters_with_wide_characters() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "replace_non_wide_characters_with_wide_characters"; let content = read_fixture(fixture_name); @@ -2224,6 +2487,7 @@ pub fn scroll_down_ansi() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2232,7 +2496,9 @@ pub fn scroll_down_ansi() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "scroll_down"; let content = read_fixture(fixture_name); @@ -2248,6 +2514,7 @@ pub fn ansi_capital_t() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2256,7 +2523,9 @@ pub fn ansi_capital_t() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let content = "foo\u{1b}[14Tbar".as_bytes(); for byte in content { @@ -2271,6 +2540,7 @@ pub fn ansi_capital_s() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2279,7 +2549,9 @@ pub fn ansi_capital_s() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let content = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nfoo\u{1b}[14Sbar".as_bytes(); for byte in content { @@ -2294,6 +2566,7 @@ fn terminal_pixel_size_reports() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -2305,7 +2578,9 @@ fn terminal_pixel_size_reports() { width: 8, }))), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "terminal_pixel_size_reports"; let content = read_fixture(fixture_name); @@ -2327,6 +2602,7 @@ fn terminal_pixel_size_reports_in_unsupported_terminals() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -2335,7 +2611,9 @@ fn terminal_pixel_size_reports_in_unsupported_terminals() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), // in an unsupported terminal, we don't have this info sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let fixture_name = "terminal_pixel_size_reports"; let content = read_fixture(fixture_name); @@ -2358,6 +2636,7 @@ pub fn ansi_csi_at_sign() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2366,7 +2645,9 @@ pub fn ansi_csi_at_sign() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let content = "foo\u{1b}[2D\u{1b}[2@".as_bytes(); for byte in content { @@ -2385,6 +2666,7 @@ pub fn sixel_images_are_reaped_when_scrolled_off() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2393,7 +2675,9 @@ pub fn sixel_images_are_reaped_when_scrolled_off() { Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store.clone(), + Style::default(), debug, + arrow_fonts, ); let pane_content = read_fixture("sixel-image-500px.six"); for byte in pane_content { @@ -2421,6 +2705,7 @@ pub fn sixel_images_are_reaped_when_resetting() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 112, @@ -2429,7 +2714,9 @@ pub fn sixel_images_are_reaped_when_resetting() { Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store.clone(), + Style::default(), debug, + arrow_fonts, ); let pane_content = read_fixture("sixel-image-500px.six"); for byte in pane_content { @@ -2454,6 +2741,7 @@ pub fn sixel_image_in_alternate_buffer() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 30, 112, @@ -2462,7 +2750,9 @@ pub fn sixel_image_in_alternate_buffer() { Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store.clone(), + Style::default(), debug, + arrow_fonts, ); let move_to_alternate_screen = "\u{1b}[?1049h"; @@ -2498,6 +2788,7 @@ pub fn sixel_with_image_scrolling_decsdm() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 30, 112, @@ -2506,7 +2797,9 @@ pub fn sixel_with_image_scrolling_decsdm() { Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store, + Style::default(), debug, + arrow_fonts, ); // enter DECSDM @@ -2561,6 +2854,7 @@ pub fn osc_4_background_query() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -2569,7 +2863,9 @@ pub fn osc_4_background_query() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let content = "\u{1b}]10;?\u{1b}\\"; for byte in content.as_bytes() { @@ -2592,6 +2888,7 @@ pub fn osc_4_foreground_query() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -2600,7 +2897,9 @@ pub fn osc_4_foreground_query() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let content = "\u{1b}]11;?\u{1b}\\"; for byte in content.as_bytes() { @@ -2625,6 +2924,7 @@ pub fn osc_4_color_query() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(color_codes)); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -2633,7 +2933,9 @@ pub fn osc_4_color_query() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let content = "\u{1b}]4;222;?\u{1b}\\"; for byte in content.as_bytes() { @@ -2656,6 +2958,7 @@ pub fn xtsmgraphics_color_register_count() { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -2664,7 +2967,9 @@ pub fn xtsmgraphics_color_register_count() { Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let content = "\u{1b}[?1;1;S\u{1b}\\"; for byte in content.as_bytes() { @@ -2691,6 +2996,7 @@ pub fn xtsmgraphics_pixel_graphics_geometry() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 51, 97, @@ -2699,7 +3005,9 @@ pub fn xtsmgraphics_pixel_graphics_geometry() { Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let content = "\u{1b}[?2;1;S\u{1b}\\"; for byte in content.as_bytes() { @@ -2726,6 +3034,7 @@ pub fn cursor_hide_persists_through_alternate_screen() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( 30, 112, @@ -2734,7 +3043,9 @@ pub fn cursor_hide_persists_through_alternate_screen() { Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let hide_cursor = "\u{1b}[?25l"; @@ -2768,3 +3079,219 @@ pub fn cursor_hide_persists_through_alternate_screen() { "Cursor still shown away from alternate screen" ); } + +#[test] +fn table_ui_component() { + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let mut grid = Grid::new( + 41, + 110, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + ); + let fixture_name = "table-ui-component"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +fn table_ui_component_with_coordinates() { + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let mut grid = Grid::new( + 41, + 110, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + ); + let fixture_name = "table-ui-component-with-coordinates"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +fn ribbon_ui_component() { + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let mut grid = Grid::new( + 41, + 110, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + ); + let fixture_name = "ribbon-ui-component"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +fn ribbon_ui_component_with_coordinates() { + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let mut grid = Grid::new( + 41, + 110, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + ); + let fixture_name = "ribbon-ui-component-with-coordinates"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +fn nested_list_ui_component() { + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let mut grid = Grid::new( + 41, + 120, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + ); + let fixture_name = "nested-list-ui-component"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +fn nested_list_ui_component_with_coordinates() { + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let mut grid = Grid::new( + 41, + 120, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + ); + let fixture_name = "nested-list-ui-component-with-coordinates"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +fn text_ui_component() { + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let mut grid = Grid::new( + 41, + 120, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + ); + let fixture_name = "text-ui-component"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +fn text_ui_component_with_coordinates() { + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let mut grid = Grid::new( + 41, + 120, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + ); + let fixture_name = "text-ui-component-with-coordinates"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} diff --git a/zellij-server/src/panes/unit/search_in_pane_tests.rs b/zellij-server/src/panes/unit/search_in_pane_tests.rs index 346eb40b..713a2288 100644 --- a/zellij-server/src/panes/unit/search_in_pane_tests.rs +++ b/zellij-server/src/panes/unit/search_in_pane_tests.rs @@ -29,6 +29,7 @@ fn create_pane() -> TerminalPane { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -43,6 +44,7 @@ fn create_pane() -> TerminalPane { None, None, debug, + arrow_fonts, ); // 0 is the pane index let content = read_fixture(); terminal_pane.handle_pty_bytes(content); diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__nested_list_ui_component.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__nested_list_ui_component.snap new file mode 100644 index 00000000..b7fdb412 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__nested_list_ui_component.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 3210 +expression: "format!(\"{:?}\", grid)" +--- +00 (C): > item 1 +01 (C): > item 2 +02 (C): - item 3 +03 (C): > item 4 +04 (C): - item 5 lsdkfjlskdj flksdjf lksdj flksjd f +05 (C): > item 6 sldkfjslkdfj lsdkjf lskdjf lskdjf lksdjf lskdjf +06 (C): > item 7 +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__nested_list_ui_component_with_coordinates.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__nested_list_ui_component_with_coordinates.snap new file mode 100644 index 00000000..e781c3ad --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__nested_list_ui_component_with_coordinates.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 3237 +expression: "format!(\"{:?}\", grid)" +--- +00 (C): +01 (C): > item 1 with some +02 (C): - item 2 with som +03 (C): > item 3 is a real +04 (C): +05 (C): +06 (C): +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_selected_ui_component.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_selected_ui_component.snap new file mode 100644 index 00000000..7f464173 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_selected_ui_component.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 2949 +expression: "format!(\"{:?}\", grid)" +--- +00 (C):  RESIZE  +01 (C): +02 (C): +03 (C): +04 (C): +05 (C): +06 (C): +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_ui_component.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_ui_component.snap new file mode 100644 index 00000000..0fc9c808 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_ui_component.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 2921 +expression: "format!(\"{:?}\", grid)" +--- +00 (C):  RESIZE  +01 (C): +02 (C): +03 (C): +04 (C): +05 (C): +06 (C): +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_ui_component_with_coordinates.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_ui_component_with_coordinates.snap new file mode 100644 index 00000000..840e8c2c --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__ribbon_ui_component_with_coordinates.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 3183 +expression: "format!(\"{:?}\", grid)" +--- +00 (C): +01 (C): +02 (C):  ribbon 1  +03 (C): +04 (C): +05 (C): +06 (C): +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component.snap new file mode 100644 index 00000000..94242076 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 3102 +expression: "format!(\"{:?}\", grid)" +--- +00 (C): title1 title2 title3 title4 title5 +01 (C): 1lksdjflksdjf lkjdsflksjdf lkjsdlkfjsfd lkjsdlkjfd lkjdslkjsdf +02 (C): 2lksdjflksdjf lkjdsflksjdf lkj😳😳sdlkfjsfd lkjsdlkjfd lkjdslkjsdf +03 (C): 3lksdjflksdjf lkjdsflksjdf lkjsd😳lkfjsfd lkjsdlkjfd lkjdslkjsdf +04 (C): 4lksdjflks222djf lk😳222jdsflksjdf lk222jsdlkfjsfd lkwwwjsdlkjfd lkjdslkjsdf +05 (C): 5lksdjflksdjf lkjdsflksjdf lkjsdlkfjsfd lksdjflksjfdlkjsdlkjfd lkjdrrrrslkjsdf +06 (C): 6lksdjflk😳sdjf l😳kjdsflksjdf lkjsdlkfjsfd lkjsdlkjfd lwwkwkjdslkjsdf +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component_with_coordinates.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component_with_coordinates.snap new file mode 100644 index 00000000..2431a89e --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__table_ui_component_with_coordinates.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 3129 +expression: "format!(\"{:?}\", grid)" +--- +00 (C): +01 (C): +02 (C): +03 (C): +04 (C): title1 +05 (C): content 1 +06 (C): content 11 +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__text_ui_component.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__text_ui_component.snap new file mode 100644 index 00000000..f2f219bf --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__text_ui_component.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 3264 +expression: "format!(\"{:?}\", grid)" +--- +00 (C): foo bar baz +01 (C): +02 (C): +03 (C): +04 (C): +05 (C): +06 (C): +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__text_ui_component_with_coordinates.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__text_ui_component_with_coordinates.snap new file mode 100644 index 00000000..beb899a2 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__text_ui_component_with_coordinates.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 3291 +expression: "format!(\"{:?}\", grid)" +--- +00 (C): +01 (C): +02 (C): +03 (C): +04 (C): foo bar baz +05 (C): +06 (C): +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): + diff --git a/zellij-server/src/panes/unit/terminal_pane_tests.rs b/zellij-server/src/panes/unit/terminal_pane_tests.rs index 8b0a6c41..e771dd42 100644 --- a/zellij-server/src/panes/unit/terminal_pane_tests.rs +++ b/zellij-server/src/panes/unit/terminal_pane_tests.rs @@ -37,6 +37,7 @@ pub fn scrolling_inside_a_pane() { let terminal_emulator_colors = Rc::new(RefCell::new(Palette::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -51,6 +52,7 @@ pub fn scrolling_inside_a_pane() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let mut text_to_fill_pane = String::new(); for i in 0..30 { @@ -81,6 +83,7 @@ pub fn sixel_image_inside_terminal_pane() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -95,6 +98,7 @@ pub fn sixel_image_inside_terminal_pane() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let sixel_image_bytes = "\u{1b}Pq #0;2;0;0;0#1;2;100;100;0#2;2;0;100;0 @@ -125,6 +129,7 @@ pub fn partial_sixel_image_inside_terminal_pane() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -139,6 +144,7 @@ pub fn partial_sixel_image_inside_terminal_pane() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let pane_content = read_fixture("sixel-image-500px.six"); terminal_pane.handle_pty_bytes(pane_content); @@ -163,6 +169,7 @@ pub fn overflowing_sixel_image_inside_terminal_pane() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -177,6 +184,7 @@ pub fn overflowing_sixel_image_inside_terminal_pane() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let pane_content = read_fixture("sixel-image-500px.six"); terminal_pane.handle_pty_bytes(pane_content); @@ -200,6 +208,7 @@ pub fn scrolling_through_a_sixel_image() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -214,6 +223,7 @@ pub fn scrolling_through_a_sixel_image() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let mut text_to_fill_pane = String::new(); for i in 0..30 { @@ -248,6 +258,7 @@ pub fn multiple_sixel_images_in_pane() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -262,6 +273,7 @@ pub fn multiple_sixel_images_in_pane() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let mut text_to_fill_pane = String::new(); for i in 0..5 { @@ -294,6 +306,7 @@ pub fn resizing_pane_with_sixel_images() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -308,6 +321,7 @@ pub fn resizing_pane_with_sixel_images() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let mut text_to_fill_pane = String::new(); for i in 0..5 { @@ -343,6 +357,7 @@ pub fn changing_character_cell_size_with_sixel_images() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -357,6 +372,7 @@ pub fn changing_character_cell_size_with_sixel_images() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let mut text_to_fill_pane = String::new(); for i in 0..5 { @@ -397,6 +413,7 @@ pub fn keep_working_after_corrupted_sixel_image() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -411,6 +428,7 @@ pub fn keep_working_after_corrupted_sixel_image() { None, None, debug, + arrow_fonts, ); // 0 is the pane index let sixel_image_bytes = "\u{1b}PI AM CORRUPTED BWAHAHAq @@ -449,6 +467,7 @@ pub fn pane_with_frame_position_is_on_frame() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -463,6 +482,7 @@ pub fn pane_with_frame_position_is_on_frame() { None, None, debug, + arrow_fonts, ); // 0 is the pane index terminal_pane.set_content_offset(Offset::frame(1)); @@ -537,6 +557,7 @@ pub fn pane_with_bottom_and_right_borders_position_is_on_frame() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -551,6 +572,7 @@ pub fn pane_with_bottom_and_right_borders_position_is_on_frame() { None, None, debug, + arrow_fonts, ); // 0 is the pane index terminal_pane.set_content_offset(Offset::shift(1, 1)); @@ -625,6 +647,7 @@ pub fn frameless_pane_position_is_on_frame() { height: 21, }))); let debug = false; + let arrow_fonts = true; let mut terminal_pane = TerminalPane::new( pid, fake_win_size, @@ -639,6 +662,7 @@ pub fn frameless_pane_position_is_on_frame() { None, None, debug, + arrow_fonts, ); // 0 is the pane index terminal_pane.set_content_offset(Offset::default()); diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 58286185..4f5833f4 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -560,6 +560,7 @@ pub(crate) struct Screen { // also be this session default_layout: Box, default_shell: Option, + arrow_fonts: bool, } impl Screen { @@ -579,6 +580,7 @@ impl Screen { session_serialization: bool, serialize_pane_viewport: bool, scrollback_lines_to_serialize: Option, + arrow_fonts: bool, ) -> Self { let session_name = mode_info.session_name.clone().unwrap_or_default(); let session_info = SessionInfo::new(session_name.clone()); @@ -613,6 +615,7 @@ impl Screen { session_serialization, serialize_pane_viewport, scrollback_lines_to_serialize, + arrow_fonts, } } @@ -1151,6 +1154,7 @@ impl Screen { swap_layouts, self.default_shell.clone(), self.debug, + self.arrow_fonts, ); self.tabs.insert(tab_index, tab); Ok(()) @@ -2034,7 +2038,7 @@ pub(crate) fn screen_thread_main( debug: bool, default_layout: Box, ) -> Result<()> { - let capabilities = config_options.simplified_ui; + let arrow_fonts = !config_options.simplified_ui.unwrap_or_default(); let draw_pane_frames = config_options.pane_frames.unwrap_or(true); let auto_layout = config_options.auto_layout.unwrap_or(true); let session_serialization = config_options.session_serialization.unwrap_or(true); @@ -2057,7 +2061,8 @@ pub(crate) fn screen_thread_main( config_options.default_mode.unwrap_or_default(), &client_attributes, PluginCapabilities { - arrow_fonts: capabilities.unwrap_or_default(), + // ¯\_(ツ)_/¯ + arrow_fonts: !arrow_fonts, }, ), draw_pane_frames, @@ -2070,6 +2075,7 @@ pub(crate) fn screen_thread_main( session_serialization, serialize_pane_viewport, scrollback_lines_to_serialize, + arrow_fonts, ); let mut pending_tab_ids: HashSet = HashSet::new(); diff --git a/zellij-server/src/tab/layout_applier.rs b/zellij-server/src/tab/layout_applier.rs index 80adf14a..7acd7e85 100644 --- a/zellij-server/src/tab/layout_applier.rs +++ b/zellij-server/src/tab/layout_applier.rs @@ -41,6 +41,7 @@ pub struct LayoutApplier<'a> { focus_pane_id: &'a mut Option, os_api: Box, debug: bool, + arrow_fonts: bool, } impl<'a> LayoutApplier<'a> { @@ -61,6 +62,7 @@ impl<'a> LayoutApplier<'a> { focus_pane_id: &'a mut Option, os_api: &Box, debug: bool, + arrow_fonts: bool, ) -> Self { let viewport = viewport.clone(); let senders = senders.clone(); @@ -90,6 +92,7 @@ impl<'a> LayoutApplier<'a> { focus_pane_id, os_api, debug, + arrow_fonts, } } pub fn apply_layout( @@ -256,6 +259,7 @@ impl<'a> LayoutApplier<'a> { self.style, layout.run.clone(), self.debug, + self.arrow_fonts, ); if let Some(pane_initial_contents) = &layout.pane_initial_contents { new_plugin.handle_pty_bytes(pane_initial_contents.as_bytes().into()); @@ -292,6 +296,7 @@ impl<'a> LayoutApplier<'a> { initial_title, layout.run.clone(), self.debug, + self.arrow_fonts, ); if let Some(pane_initial_contents) = &layout.pane_initial_contents { new_pane.handle_pty_bytes(pane_initial_contents.as_bytes().into()); @@ -381,6 +386,7 @@ impl<'a> LayoutApplier<'a> { self.style, floating_pane_layout.run.clone(), self.debug, + self.arrow_fonts, ); if let Some(pane_initial_contents) = &floating_pane_layout.pane_initial_contents { new_pane.handle_pty_bytes(pane_initial_contents.as_bytes().into()); @@ -420,6 +426,7 @@ impl<'a> LayoutApplier<'a> { initial_title, floating_pane_layout.run.clone(), self.debug, + self.arrow_fonts, ); if let Some(pane_initial_contents) = &floating_pane_layout.pane_initial_contents { new_pane.handle_pty_bytes(pane_initial_contents.as_bytes().into()); diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index f441e729..50b9c2e4 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -185,6 +185,7 @@ pub(crate) struct Tab { swap_layouts: SwapLayouts, default_shell: Option, debug: bool, + arrow_fonts: bool, } #[derive(Clone, Debug, Default, Serialize, Deserialize)] @@ -533,6 +534,7 @@ impl Tab { swap_layouts: (Vec, Vec), default_shell: Option, debug: bool, + arrow_fonts: bool, ) -> Self { let name = if name.is_empty() { format!("Tab #{}", index + 1) @@ -621,6 +623,7 @@ impl Tab { swap_layouts, default_shell, debug, + arrow_fonts, } } @@ -652,6 +655,7 @@ impl Tab { &mut self.focus_pane_id, &self.os_api, self.debug, + self.arrow_fonts, ) .apply_layout( layout, @@ -713,6 +717,7 @@ impl Tab { &mut self.focus_pane_id, &self.os_api, self.debug, + self.arrow_fonts, ) .apply_floating_panes_layout_to_existing_panes( &layout_candidate, @@ -767,6 +772,7 @@ impl Tab { &mut self.focus_pane_id, &self.os_api, self.debug, + self.arrow_fonts, ) .apply_tiled_panes_layout_to_existing_panes( &layout_candidate, @@ -1053,6 +1059,7 @@ impl Tab { initial_pane_title, invoked_with, self.debug, + self.arrow_fonts, )) as Box }, PaneId::Plugin(plugin_pid) => { @@ -1075,6 +1082,7 @@ impl Tab { self.style, invoked_with, self.debug, + self.arrow_fonts, )) as Box }, }; @@ -1111,6 +1119,7 @@ impl Tab { None, None, self.debug, + self.arrow_fonts, ); new_pane.update_name("EDITING SCROLLBACK"); // we do this here and not in the // constructor so it won't be overrided @@ -1183,6 +1192,7 @@ impl Tab { None, run, self.debug, + self.arrow_fonts, ); let replaced_pane = if self.floating_panes.panes_contain(&old_pane_id) { self.floating_panes @@ -1235,6 +1245,7 @@ impl Tab { self.style, run, self.debug, + self.arrow_fonts, ); let replaced_pane = if self.floating_panes.panes_contain(&old_pane_id) { self.floating_panes @@ -1303,6 +1314,7 @@ impl Tab { initial_pane_title, None, self.debug, + self.arrow_fonts, ); self.tiled_panes .split_pane_horizontally(pid, Box::new(new_terminal), client_id); @@ -1360,6 +1372,7 @@ impl Tab { initial_pane_title, None, self.debug, + self.arrow_fonts, ); self.tiled_panes .split_pane_vertically(pid, Box::new(new_terminal), client_id); diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs index 7574ee5e..21e7d0d7 100644 --- a/zellij-server/src/tab/unit/tab_integration_tests.rs +++ b/zellij-server/src/tab/unit/tab_integration_tests.rs @@ -224,6 +224,7 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab { let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -247,6 +248,7 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab { (vec![], vec![]), None, debug, + arrow_fonts, ); tab.apply_layout( TiledPaneLayout::default(), @@ -297,6 +299,7 @@ fn create_new_tab_with_swap_layouts( let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -320,6 +323,7 @@ fn create_new_tab_with_swap_layouts( swap_layouts, None, debug, + arrow_fonts, ); let ( base_layout, @@ -372,6 +376,7 @@ fn create_new_tab_with_os_api( let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -395,6 +400,7 @@ fn create_new_tab_with_os_api( (vec![], vec![]), // swap layouts None, debug, + arrow_fonts, ); tab.apply_layout( TiledPaneLayout::default(), @@ -433,6 +439,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str) let layout = Layout::from_str(layout, "layout_file_name".into(), None, None).unwrap(); let (tab_layout, floating_panes_layout) = layout.new_tab(); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -456,6 +463,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str) (vec![], vec![]), // swap layouts None, debug, + arrow_fonts, ); let pane_ids = tab_layout .extract_run_instructions() @@ -508,6 +516,7 @@ fn create_new_tab_with_mock_pty_writer( let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -531,6 +540,7 @@ fn create_new_tab_with_mock_pty_writer( (vec![], vec![]), // swap layouts None, debug, + arrow_fonts, ); tab.apply_layout( TiledPaneLayout::default(), @@ -574,6 +584,7 @@ fn create_new_tab_with_sixel_support( let copy_options = CopyOptions::default(); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -597,6 +608,7 @@ fn create_new_tab_with_sixel_support( (vec![], vec![]), // swap layouts None, debug, + arrow_fonts, ); tab.apply_layout( TiledPaneLayout::default(), @@ -633,6 +645,7 @@ fn take_snapshot(ansi_instructions: &str, rows: usize, columns: usize, palette: height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( rows, columns, @@ -641,7 +654,9 @@ fn take_snapshot(ansi_instructions: &str, rows: usize, columns: usize, palette: Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let mut vte_parser = vte::Parser::new(); for &byte in ansi_instructions.as_bytes() { @@ -663,6 +678,7 @@ fn take_snapshot_with_sixel( height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( rows, columns, @@ -671,7 +687,9 @@ fn take_snapshot_with_sixel( Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let mut vte_parser = vte::Parser::new(); for &byte in ansi_instructions.as_bytes() { @@ -690,6 +708,7 @@ fn take_snapshot_and_cursor_position( let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( rows, columns, @@ -698,7 +717,9 @@ fn take_snapshot_and_cursor_position( Rc::new(RefCell::new(LinkHandler::new())), Rc::new(RefCell::new(None)), sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let mut vte_parser = vte::Parser::new(); for &byte in ansi_instructions.as_bytes() { diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs index 7ba629b8..b1e2110a 100644 --- a/zellij-server/src/tab/unit/tab_tests.rs +++ b/zellij-server/src/tab/unit/tab_tests.rs @@ -165,6 +165,7 @@ fn create_new_tab(size: Size) -> Tab { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -188,6 +189,7 @@ fn create_new_tab(size: Size) -> Tab { (vec![], vec![]), // swap layouts None, debug, + arrow_fonts, ); tab.apply_layout( TiledPaneLayout::default(), @@ -223,6 +225,7 @@ fn create_new_tab_with_layout(size: Size, layout: TiledPaneLayout) -> Tab { let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -246,6 +249,7 @@ fn create_new_tab_with_layout(size: Size, layout: TiledPaneLayout) -> Tab { (vec![], vec![]), // swap layouts None, debug, + arrow_fonts, ); let mut new_terminal_ids = vec![]; for i in 0..layout.extract_run_instructions().len() { @@ -287,6 +291,7 @@ fn create_new_tab_with_cell_size( let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); let debug = false; + let arrow_fonts = true; let mut tab = Tab::new( index, position, @@ -310,6 +315,7 @@ fn create_new_tab_with_cell_size( (vec![], vec![]), // swap layouts None, debug, + arrow_fonts, ); tab.apply_layout( TiledPaneLayout::default(), diff --git a/zellij-server/src/ui/components/component_coordinates.rs b/zellij-server/src/ui/components/component_coordinates.rs new file mode 100644 index 00000000..b6029362 --- /dev/null +++ b/zellij-server/src/ui/components/component_coordinates.rs @@ -0,0 +1,43 @@ +use std::fmt::{self, Display, Formatter}; + +#[derive(Debug, Clone)] +pub struct Coordinates { + pub x: usize, + pub y: usize, + pub width: Option, + pub height: Option, +} + +impl Coordinates { + pub fn stringify_with_y_offset(&self, y_offset: usize) -> String { + format!("\u{1b}[{};{}H", self.y + y_offset + 1, self.x + 1) + } +} + +impl Display for Coordinates { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "\u{1b}[{};{}H", self.y + 1, self.x + 1) + } +} + +pub fn is_too_wide( + character_width: usize, + current_width: usize, + component_coordinates: &Option, +) -> bool { + if let Some(max_width) = component_coordinates.as_ref().and_then(|p| p.width) { + if current_width + character_width > max_width { + return true; + } + } + false +} + +pub fn is_too_high(current_height: usize, component_coordinates: &Option) -> bool { + if let Some(max_height) = component_coordinates.as_ref().and_then(|p| p.height) { + if current_height > max_height { + return true; + } + } + false +} diff --git a/zellij-server/src/ui/components/mod.rs b/zellij-server/src/ui/components/mod.rs new file mode 100644 index 00000000..8fcfcc14 --- /dev/null +++ b/zellij-server/src/ui/components/mod.rs @@ -0,0 +1,187 @@ +mod component_coordinates; +mod nested_list; +mod ribbon; +mod table; +mod text; + +use crate::panes::grid::Grid; +use zellij_utils::errors::prelude::*; +use zellij_utils::{data::Style, lazy_static::lazy_static, regex::Regex, vte}; + +use component_coordinates::{is_too_high, is_too_wide, Coordinates}; +use nested_list::{nested_list, parse_nested_list_items}; +use ribbon::{emphasis_variants_for_ribbon, emphasis_variants_for_selected_ribbon, ribbon}; +use table::table; +use text::{parse_text, parse_text_params, stringify_text, text, Text}; + +macro_rules! parse_next_param { + ($next_param:expr, $type:ident, $component_name:expr, $item_name:expr) => {{ + $next_param + .and_then(|stringified_param| stringified_param.parse::<$type>().ok()) + .with_context(|| format!("{} must have {}", $component_name, $item_name))? + }}; +} + +macro_rules! parse_vte_bytes { + ($self:expr, $encoded_component:expr) => {{ + let mut vte_parser = vte::Parser::new(); + for &byte in &$encoded_component { + vte_parser.advance($self.grid, byte); + } + }}; +} + +#[derive(Debug)] +pub struct UiComponentParser<'a> { + grid: &'a mut Grid, + style: Style, + arrow_fonts: bool, +} + +impl<'a> UiComponentParser<'a> { + pub fn new(grid: &'a mut Grid, style: Style, arrow_fonts: bool) -> Self { + UiComponentParser { + grid, + style, + arrow_fonts, + } + } + pub fn parse(&mut self, bytes: Vec) -> Result<()> { + // The stages of parsing: + // 1. We decode the bytes to utf8 and get something like (as a String): `component_name;111;222;333` + // 2. We split this string by `;` to get at the parameters themselves + // 3. We extract the component name, and then behave according to the component + // 4. Some components interpret their parameters as bytes, and so have another layer of + // utf8 decoding, others would take them verbatim, some will act depending on their + // placement (eg. the `table` component treats the first two parameters as integers for + // the columns/rows of the table, and then treats the rest of the component as utf8 + // encoded bytes, each one representing one cell in the table) + // 5. Each component parses its parameters, creating a String of ANSI instructions of its + // own representing instructions to create the component + // 6. Finally, we take this string, encode it back into bytes and pass it back through the ANSI + // parser (our `Grid`) in order to create a representation of it on screen + let mut params: Vec = String::from_utf8_lossy(&bytes) + .to_string() + .split(';') + .map(|c| c.to_owned()) + .collect(); + let mut params_iter = params.iter_mut().peekable(); + let component_name = params_iter + .next() + .with_context(|| format!("ui component must have a name"))?; + + // parse coordinates + let mut component_coordinates = None; + if let Some(coordinates) = params_iter.peek() { + component_coordinates = self.parse_coordinates(coordinates)?; + if component_coordinates.is_some() { + let _ = params_iter.next(); // we just peeked, let's consume the coords now + } + } + + if component_name == &"table" { + let columns = parse_next_param!(params_iter.next(), usize, "table", "columns"); + let rows = parse_next_param!(params_iter.next(), usize, "table", "rows"); + let stringified_params = parse_text_params(params_iter); + let encoded_table = table( + columns, + rows, + stringified_params, + Some(self.style.colors.green), + &self.style, + component_coordinates, + ); + parse_vte_bytes!(self, encoded_table); + Ok(()) + } else if component_name == &"ribbon" { + let stringified_params = parse_text_params(params_iter) + .into_iter() + .next() + .with_context(|| format!("a ribbon must have text"))?; + let encoded_text = ribbon( + stringified_params, + &self.style, + self.arrow_fonts, + component_coordinates, + ); + parse_vte_bytes!(self, encoded_text); + Ok(()) + } else if component_name == &"nested_list" { + let nested_list_items = parse_nested_list_items(params_iter); + let encoded_nested_list = + nested_list(nested_list_items, &self.style, component_coordinates); + parse_vte_bytes!(self, encoded_nested_list); + Ok(()) + } else if component_name == &"text" { + let stringified_params = parse_text_params(params_iter) + .into_iter() + .next() + .with_context(|| format!("text must have, well, text..."))?; + let encoded_text = text(stringified_params, &self.style, component_coordinates); + parse_vte_bytes!(self, encoded_text); + Ok(()) + } else { + Err(anyhow!("Unknown component: {}", component_name)) + } + } + fn parse_coordinates(&self, coordinates: &str) -> Result> { + lazy_static! { + static ref RE: Regex = Regex::new(r"(\d*)/(\d*)/(\d*)/(\d*)").unwrap(); + } + if let Some(captures) = RE.captures_iter(&coordinates).next() { + let x = captures[1].parse::().with_context(|| { + format!( + "Failed to parse x coordinates for string: {:?}", + coordinates + ) + })?; + let y = captures[2].parse::().with_context(|| { + format!( + "Failed to parse y coordinates for string: {:?}", + coordinates + ) + })?; + let width = captures[3].parse::().ok(); + let height = captures[4].parse::().ok(); + Ok(Some(Coordinates { + x, + y, + width, + height, + })) + } else { + Ok(None) + } + } +} + +fn parse_selected(stringified: &mut String) -> bool { + let mut selected = false; + if stringified.chars().next() == Some('x') { + selected = true; + stringified.remove(0); + } + selected +} + +fn parse_indices(stringified: &mut String) -> Vec> { + stringified + .chars() + .collect::>() + .iter() + .rposition(|c| c == &'$') + .map(|last_position| stringified.drain(0..=last_position).collect::()) + .map(|indices_string| { + let mut all_indices = vec![]; + let raw_indices_for_each_variant = indices_string.split('$'); + for index_string in raw_indices_for_each_variant { + let indices_for_variant = index_string + .split(',') + .filter_map(|s| s.parse::().ok()) + .collect(); + all_indices.push(indices_for_variant) + } + all_indices + }) + .unwrap_or_default() +} diff --git a/zellij-server/src/ui/components/nested_list.rs b/zellij-server/src/ui/components/nested_list.rs new file mode 100644 index 00000000..9b60d574 --- /dev/null +++ b/zellij-server/src/ui/components/nested_list.rs @@ -0,0 +1,142 @@ +use super::{ + is_too_high, parse_indices, parse_selected, parse_text, stringify_text, Coordinates, Text, +}; +use crate::panes::terminal_character::{AnsiCode, RESET_STYLES}; +use zellij_utils::data::Style; + +use unicode_width::UnicodeWidthChar; + +#[derive(Debug, Clone)] +pub struct NestedListItem { + pub text: Text, + pub indentation_level: usize, +} + +pub fn nested_list( + mut contents: Vec, + style: &Style, + coordinates: Option, +) -> Vec { + let mut stringified = String::new(); + let max_width = coordinates + .as_ref() + .and_then(|c| c.width) + .unwrap_or_else(|| max_nested_item_width(&contents)); + for (line_index, line_item) in contents.drain(..).enumerate() { + if is_too_high(line_index + 1, &coordinates) { + break; + } + let mut reset_styles_for_item = RESET_STYLES; + if line_item.text.selected { + reset_styles_for_item.background = None; + }; + let padding = line_item.indentation_level * 2 + 1; + let bulletin = if line_item.indentation_level % 2 == 0 { + "> " + } else { + "- " + }; + let text_style = reset_styles_for_item.bold(Some(AnsiCode::On)); + let (mut text, text_width) = stringify_text( + &line_item.text, + Some(padding + bulletin.len()), + &coordinates, + style, + text_style, + ); + text = pad_line(text, max_width, padding, text_width); + let go_to_row_instruction = coordinates + .as_ref() + .map(|c| c.stringify_with_y_offset(line_index)) + .unwrap_or_else(|| { + if line_index != 0 { + format!("\n\r") + } else { + "".to_owned() + } + }); + if line_item.text.selected { + let selected_background = RESET_STYLES.background(Some(style.colors.bg.into())); + stringified.push_str(&format!( + "{}{}{}{:padding$}{bulletin}{}{text}{}", + go_to_row_instruction, + selected_background, + reset_styles_for_item, + " ", + text_style, + RESET_STYLES + )); + } else { + stringified.push_str(&format!( + "{}{}{:padding$}{bulletin}{}{text}{}", + go_to_row_instruction, reset_styles_for_item, " ", text_style, RESET_STYLES + )); + } + } + stringified.as_bytes().to_vec() +} + +pub fn parse_nested_list_items<'a>( + params_iter: impl Iterator, +) -> Vec { + params_iter + .flat_map(|mut stringified| { + let indentation_level = parse_indentation_level(&mut stringified); + let selected = parse_selected(&mut stringified); + let indices = parse_indices(&mut stringified); + let text = parse_text(&mut stringified).map_err(|e| e.to_string())?; + let text = Text { + text, + selected, + indices, + }; + Ok::(NestedListItem { + text, + indentation_level, + }) + }) + .collect::>() +} + +fn parse_indentation_level(stringified: &mut String) -> usize { + let mut indentation_level = 0; + loop { + if stringified.is_empty() { + break; + } + if stringified.chars().next() == Some('|') { + stringified.remove(0); + indentation_level += 1; + } else { + break; + } + } + indentation_level +} + +fn max_nested_item_width(contents: &Vec) -> usize { + let mut width_of_longest_line = 0; + for line_item in contents.iter() { + let mut line_item_text_width = 0; + for character in line_item.text.text.chars() { + let character_width = character.width().unwrap_or(0); + line_item_text_width += character_width; + } + let bulletin_width = 2; + let padding = line_item.indentation_level * 2 + 1; + let total_width = line_item_text_width + bulletin_width + padding; + if width_of_longest_line < total_width { + width_of_longest_line = total_width; + } + } + width_of_longest_line +} + +fn pad_line(text: String, max_width: usize, padding: usize, text_width: usize) -> String { + if max_width > text_width + padding + 2 { + // 2 is the bulletin + let end_padding = max_width.saturating_sub(text_width + padding + 2); + return format!("{}{:end_padding$}", text, " "); + } + text +} diff --git a/zellij-server/src/ui/components/ribbon.rs b/zellij-server/src/ui/components/ribbon.rs new file mode 100644 index 00000000..7f0f7815 --- /dev/null +++ b/zellij-server/src/ui/components/ribbon.rs @@ -0,0 +1,115 @@ +use super::{is_too_wide, Coordinates, Text}; +use crate::panes::terminal_character::{AnsiCode, CharacterStyles, RESET_STYLES}; +use unicode_width::UnicodeWidthChar; +use zellij_utils::data::{PaletteColor, Style}; + +static ARROW_SEPARATOR: &str = ""; + +pub fn ribbon( + content: Text, + style: &Style, + arrow_fonts: bool, + component_coordinates: Option, +) -> Vec { + let colors = style.colors; + let (first_arrow_styles, text_style, last_arrow_styles) = if content.selected { + ( + character_style(colors.black, colors.green), + character_style(colors.black, colors.green), + character_style(colors.green, colors.black), + ) + } else { + ( + character_style(colors.black, colors.fg), + character_style(colors.black, colors.fg), + character_style(colors.fg, colors.black), + ) + }; + let (text, _text_width) = + stringify_ribbon_text(&content, &component_coordinates, style, text_style); + let mut stringified = component_coordinates + .map(|c| c.to_string()) + .unwrap_or_else(|| String::new()); + let arrow = if arrow_fonts { ARROW_SEPARATOR } else { "" }; + stringified.push_str(&format!( + "{}{}{}{} {} {}{}{}", + RESET_STYLES, + first_arrow_styles, + arrow, + text_style, + text, + last_arrow_styles, + arrow, + RESET_STYLES + )); + stringified.as_bytes().to_vec() +} + +pub fn emphasis_variants_for_ribbon(style: &Style) -> [PaletteColor; 4] { + [ + style.colors.red, + style.colors.white, + style.colors.blue, + style.colors.magenta, + ] +} + +pub fn emphasis_variants_for_selected_ribbon(style: &Style) -> [PaletteColor; 4] { + [ + style.colors.red, + style.colors.orange, + style.colors.magenta, + style.colors.blue, + ] +} + +fn stringify_ribbon_text( + text: &Text, + coordinates: &Option, + style: &Style, + text_style: CharacterStyles, +) -> (String, usize) { + let mut stringified = String::new(); + let mut text_width = 0; + for (i, character) in text.text.chars().enumerate() { + let character_width = character.width().unwrap_or(0); + if is_too_wide(character_width, text_width, &coordinates) { + break; + } + if !text.indices.is_empty() { + let character_with_styling = + color_ribbon_index_character(character, i, &text, style, text_style); + stringified.push_str(&character_with_styling); + } else { + stringified.push(character); + } + text_width += character_width; + } + (stringified, text_width) +} + +fn color_ribbon_index_character( + character: char, + index: usize, + text: &Text, + style: &Style, + base_style: CharacterStyles, +) -> String { + let character_style = if text.selected { + text.style_of_index_for_selected_ribbon(index, style) + .map(|foreground_style| base_style.foreground(Some(foreground_style.into()))) + .unwrap_or(base_style) + } else { + text.style_of_index_for_ribbon(index, style) + .map(|foreground_style| base_style.foreground(Some(foreground_style.into()))) + .unwrap_or(base_style) + }; + format!("{}{}{}", character_style, character, base_style) +} + +fn character_style(foreground: PaletteColor, background: PaletteColor) -> CharacterStyles { + RESET_STYLES + .foreground(Some(foreground.into())) + .background(Some(background.into())) + .bold(Some(AnsiCode::On)) +} diff --git a/zellij-server/src/ui/components/table.rs b/zellij-server/src/ui/components/table.rs new file mode 100644 index 00000000..4842f93e --- /dev/null +++ b/zellij-server/src/ui/components/table.rs @@ -0,0 +1,105 @@ +use super::{is_too_high, is_too_wide, stringify_text, Coordinates, Text}; +use crate::panes::terminal_character::{AnsiCode, RESET_STYLES}; +use std::collections::BTreeMap; +use zellij_utils::{ + data::{PaletteColor, Style}, + shared::ansi_len, +}; + +pub fn table( + columns: usize, + _rows: usize, + contents: Vec, + title_color: Option, + style: &Style, + coordinates: Option, +) -> Vec { + let mut stringified = String::new(); + // we first arrange the data by columns so that we can pad them by the widest one + let stringified_columns = stringify_table_columns(contents, columns); + let stringified_rows = stringify_table_rows(stringified_columns, &coordinates); + let title_styles = RESET_STYLES + .foreground(title_color.map(|t| t.into())) + .bold(Some(AnsiCode::On)); + let cell_styles = RESET_STYLES.bold(Some(AnsiCode::On)); + for (row_index, (_, row)) in stringified_rows.into_iter().enumerate() { + let is_title_row = row_index == 0; + if is_too_high(row_index + 1, &coordinates) { + break; + } + for cell in row { + let mut reset_styles_for_item = RESET_STYLES; + let mut text_style = if is_title_row { + title_styles + } else { + cell_styles + }; + if cell.selected { + reset_styles_for_item.background = None; + text_style = text_style.background(Some(style.colors.bg.into())); + } + // here we intentionally don't pass our coordinates even if we have them, because + // these cells have already been padded and truncated + let (text, _text_width) = stringify_text(&cell, None, &None, style, text_style); + stringified.push_str(&format!("{}{}{} ", text_style, text, reset_styles_for_item)); + } + let next_row_instruction = coordinates + .as_ref() + .map(|c| c.stringify_with_y_offset(row_index + 1)) + .unwrap_or_else(|| format!("\n\r")); + stringified.push_str(&next_row_instruction); + } + if let Some(coordinates) = coordinates { + format!("{}{}", coordinates, stringified) + .as_bytes() + .to_vec() + } else { + stringified.as_bytes().to_vec() + } +} + +fn stringify_table_columns(contents: Vec, columns: usize) -> BTreeMap> { + let mut stringified_columns: BTreeMap> = BTreeMap::new(); + for (i, cell) in contents.into_iter().enumerate() { + let column_index = i % columns; + stringified_columns + .entry(column_index) + .or_insert_with(Vec::new) + .push(cell); + } + stringified_columns +} + +fn max_table_column_width(column: &Vec) -> usize { + let mut max_column_width = 0; + for cell in column { + let cell_width = ansi_len(&cell.text); + if cell_width > max_column_width { + max_column_width = cell_width; + } + } + max_column_width +} + +fn stringify_table_rows( + stringified_columns: BTreeMap>, + coordinates: &Option, +) -> BTreeMap> { + let mut stringified_rows: BTreeMap> = BTreeMap::new(); + let mut row_width = 0; + for (_, column) in stringified_columns.into_iter() { + let max_column_width = max_table_column_width(&column); + if is_too_wide(max_column_width + 1, row_width, &coordinates) { + break; + } + row_width += max_column_width + 1; + for (row_index, mut cell) in column.into_iter().enumerate() { + cell.pad_text(max_column_width); + stringified_rows + .entry(row_index) + .or_insert_with(Vec::new) + .push(cell); + } + } + stringified_rows +} diff --git a/zellij-server/src/ui/components/text.rs b/zellij-server/src/ui/components/text.rs new file mode 100644 index 00000000..cb94eebe --- /dev/null +++ b/zellij-server/src/ui/components/text.rs @@ -0,0 +1,166 @@ +use super::{ + emphasis_variants_for_ribbon, emphasis_variants_for_selected_ribbon, is_too_wide, + parse_indices, parse_selected, Coordinates, +}; +use crate::panes::terminal_character::{AnsiCode, CharacterStyles, RESET_STYLES}; +use zellij_utils::{ + data::{PaletteColor, Style}, + shared::ansi_len, +}; + +use unicode_width::UnicodeWidthChar; +use zellij_utils::errors::prelude::*; + +pub fn text(content: Text, style: &Style, component_coordinates: Option) -> Vec { + let mut text_style = RESET_STYLES.bold(Some(AnsiCode::On)); + if content.selected { + text_style = text_style.background(Some(style.colors.bg.into())); + } + let (text, _text_width) = + stringify_text(&content, None, &component_coordinates, style, text_style); + match component_coordinates { + Some(component_coordinates) => format!("{}{}{}", component_coordinates, text_style, text) + .as_bytes() + .to_vec(), + None => format!("{}{}", text_style, text).as_bytes().to_vec(), + } +} + +pub fn stringify_text( + text: &Text, + left_padding: Option, + coordinates: &Option, + style: &Style, + text_style: CharacterStyles, +) -> (String, usize) { + let mut text_width = 0; + let mut stringified = String::new(); + for (i, character) in text.text.chars().enumerate() { + let character_width = character.width().unwrap_or(0); + if is_too_wide( + character_width, + left_padding.unwrap_or(0) + text_width, + &coordinates, + ) { + break; + } + text_width += character_width; + if !text.indices.is_empty() { + let character_with_styling = + color_index_character(character, i, &text, style, text_style); + stringified.push_str(&character_with_styling); + } else { + stringified.push(character); + } + } + (stringified, text_width) +} + +pub fn color_index_character( + character: char, + index: usize, + text: &Text, + style: &Style, + base_text_style: CharacterStyles, +) -> String { + let character_style = text + .style_of_index(index, style) + .map(|foreground_style| base_text_style.foreground(Some(foreground_style.into()))) + .unwrap_or(base_text_style); + format!("{}{}{}", character_style, character, base_text_style) +} + +pub fn emphasis_variants(style: &Style) -> [PaletteColor; 4] { + [ + style.colors.orange, + style.colors.cyan, + style.colors.green, + style.colors.magenta, + ] +} + +pub fn parse_text_params<'a>(params_iter: impl Iterator) -> Vec { + params_iter + .flat_map(|mut stringified| { + let selected = parse_selected(&mut stringified); + let indices = parse_indices(&mut stringified); + let text = parse_text(&mut stringified).map_err(|e| e.to_string())?; + Ok::(Text { + text, + selected, + indices, + }) + }) + .collect::>() +} + +#[derive(Debug, Clone)] +pub struct Text { + pub text: String, + pub selected: bool, + pub indices: Vec>, +} + +impl Text { + pub fn pad_text(&mut self, max_column_width: usize) { + for _ in ansi_len(&self.text)..max_column_width { + self.text.push(' '); + } + } + pub fn style_of_index(&self, index: usize, style: &Style) -> Option { + let index_variant_styles = emphasis_variants(style); + for i in (0..=3).rev() { + // we do this in reverse to give precedence to the last applied + // style + if let Some(indices) = self.indices.get(i) { + if indices.contains(&index) { + return Some(index_variant_styles[i]); + } + } + } + None + } + pub fn style_of_index_for_ribbon(&self, index: usize, style: &Style) -> Option { + let index_variant_styles = emphasis_variants_for_ribbon(style); + for i in (0..=3).rev() { + // we do this in reverse to give precedence to the last applied + // style + if let Some(indices) = self.indices.get(i) { + if indices.contains(&index) { + return Some(index_variant_styles[i]); + } + } + } + None + } + pub fn style_of_index_for_selected_ribbon( + &self, + index: usize, + style: &Style, + ) -> Option { + let index_variant_styles = emphasis_variants_for_selected_ribbon(style); + for i in (0..=3).rev() { + // we do this in reverse to give precedence to the last applied + // style + if let Some(indices) = self.indices.get(i) { + if indices.contains(&index) { + return Some(index_variant_styles[i]); + } + } + } + None + } +} + +pub fn parse_text(stringified: &mut String) -> Result { + let mut utf8 = vec![]; + for stringified_character in stringified.split(',') { + utf8.push( + stringified_character + .to_string() + .parse::() + .with_context(|| format!("Failed to parse utf8"))?, + ); + } + Ok(String::from_utf8_lossy(&utf8).to_string()) +} diff --git a/zellij-server/src/ui/mod.rs b/zellij-server/src/ui/mod.rs index 60cb90bf..d9d5e3a0 100644 --- a/zellij-server/src/ui/mod.rs +++ b/zellij-server/src/ui/mod.rs @@ -1,4 +1,5 @@ pub mod boundaries; +pub mod components; pub mod loading_indication; pub mod overlay; pub mod pane_boundaries_frame; diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index d5005698..689aed79 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -10,7 +10,7 @@ use crate::{ use insta::assert_snapshot; use std::path::PathBuf; use zellij_utils::cli::CliAction; -use zellij_utils::data::{Event, Resize}; +use zellij_utils::data::{Event, Resize, Style}; use zellij_utils::errors::{prelude::*, ErrorContext}; use zellij_utils::input::actions::Action; use zellij_utils::input::command::{RunCommand, TerminalAction}; @@ -67,6 +67,7 @@ fn take_snapshots_and_cursor_coordinates_from_render_events<'a>( height: 21, }))); let debug = false; + let arrow_fonts = true; let mut grid = Grid::new( screen_size.rows, screen_size.cols, @@ -75,7 +76,9 @@ fn take_snapshots_and_cursor_coordinates_from_render_events<'a>( Rc::new(RefCell::new(LinkHandler::new())), character_cell_size, sixel_image_store, + Style::default(), debug, + arrow_fonts, ); let snapshots: Vec<(Option<(usize, usize)>, String)> = all_events .filter_map(|server_instruction| { @@ -241,6 +244,7 @@ fn create_new_screen(size: Size) -> Screen { let scrollback_lines_to_serialize = None; let debug = false; + let arrow_fonts = true; let screen = Screen::new( bus, &client_attributes, @@ -256,6 +260,7 @@ fn create_new_screen(size: Size) -> Screen { session_serialization, serialize_pane_viewport, scrollback_lines_to_serialize, + arrow_fonts, ); screen } diff --git a/zellij-tile/src/lib.rs b/zellij-tile/src/lib.rs index df99e9ae..39058c29 100644 --- a/zellij-tile/src/lib.rs +++ b/zellij-tile/src/lib.rs @@ -17,6 +17,7 @@ //! pub mod prelude; pub mod shim; +pub mod ui_components; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index 86fe6040..0ec41018 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -10,6 +10,7 @@ pub use zellij_utils::plugin_api; use zellij_utils::plugin_api::plugin_command::ProtobufPluginCommand; use zellij_utils::plugin_api::plugin_ids::{ProtobufPluginIds, ProtobufZellijVersion}; +pub use super::ui_components::*; pub use zellij_utils::prost::{self, *}; // Subscription Handling diff --git a/zellij-tile/src/ui_components/mod.rs b/zellij-tile/src/ui_components/mod.rs new file mode 100644 index 00000000..0e7d4261 --- /dev/null +++ b/zellij-tile/src/ui_components/mod.rs @@ -0,0 +1,12 @@ +mod nested_list; +mod ribbon; +mod table; +mod text; + +pub use zellij_utils::plugin_api; +pub use zellij_utils::prost::{self, *}; + +pub use nested_list::*; +pub use ribbon::*; +pub use table::*; +pub use text::*; diff --git a/zellij-tile/src/ui_components/nested_list.rs b/zellij-tile/src/ui_components/nested_list.rs new file mode 100644 index 00000000..15bb890c --- /dev/null +++ b/zellij-tile/src/ui_components/nested_list.rs @@ -0,0 +1,73 @@ +use super::Text; +use std::ops::RangeBounds; + +#[derive(Debug, Default, Clone)] +pub struct NestedListItem { + indentation_level: usize, + content: Text, +} + +impl NestedListItem { + pub fn new>(text: S) -> Self + where + S: ToString, + { + NestedListItem { + content: Text::new(text), + ..Default::default() + } + } + pub fn indent(mut self, indentation_level: usize) -> Self { + self.indentation_level = indentation_level; + self + } + pub fn selected(mut self) -> Self { + self.content = self.content.selected(); + self + } + pub fn color_indices(mut self, index_level: usize, indices: Vec) -> Self { + self.content = self.content.color_indices(index_level, indices); + self + } + pub fn color_range>(mut self, index_level: usize, indices: R) -> Self { + self.content = self.content.color_range(index_level, indices); + self + } + pub fn serialize(&self) -> String { + let mut serialized = String::new(); + for _ in 0..self.indentation_level { + serialized.push('|'); + } + format!("{}{}", serialized, self.content.serialize()) + } +} + +/// render a nested list with arbitrary data +pub fn print_nested_list(items: Vec) { + let items = items + .into_iter() + .map(|i| i.serialize()) + .collect::>() + .join(";"); + print!("\u{1b}Pznested_list;{}\u{1b}\\", items) +} + +pub fn print_nested_list_with_coordinates( + items: Vec, + x: usize, + y: usize, + width: Option, + height: Option, +) { + let width = width.map(|w| w.to_string()).unwrap_or_default(); + let height = height.map(|h| h.to_string()).unwrap_or_default(); + let items = items + .into_iter() + .map(|i| i.serialize()) + .collect::>() + .join(";"); + print!( + "\u{1b}Pznested_list;{}/{}/{}/{};{}\u{1b}\\", + x, y, width, height, items + ) +} diff --git a/zellij-tile/src/ui_components/ribbon.rs b/zellij-tile/src/ui_components/ribbon.rs new file mode 100644 index 00000000..c0c1880e --- /dev/null +++ b/zellij-tile/src/ui_components/ribbon.rs @@ -0,0 +1,24 @@ +use super::Text; + +pub fn print_ribbon(text: Text) { + print!("\u{1b}Pzribbon;{}\u{1b}\\", text.serialize()); +} + +pub fn print_ribbon_with_coordinates( + text: Text, + x: usize, + y: usize, + width: Option, + height: Option, +) { + let width = width.map(|w| w.to_string()).unwrap_or_default(); + let height = height.map(|h| h.to_string()).unwrap_or_default(); + print!( + "\u{1b}Pzribbon;{}/{}/{}/{};{}\u{1b}\\", + x, + y, + width, + height, + text.serialize() + ); +} diff --git a/zellij-tile/src/ui_components/table.rs b/zellij-tile/src/ui_components/table.rs new file mode 100644 index 00000000..df1b833b --- /dev/null +++ b/zellij-tile/src/ui_components/table.rs @@ -0,0 +1,61 @@ +use super::Text; + +/// render a table with arbitrary data +#[derive(Debug, Clone)] +pub struct Table { + contents: Vec>, +} + +impl Table { + pub fn new() -> Self { + Table { contents: vec![] } + } + pub fn add_row(mut self, row: Vec) -> Self { + self.contents + .push(row.iter().map(|c| Text::new(c.to_string())).collect()); + self + } + pub fn add_styled_row(mut self, row: Vec) -> Self { + self.contents.push(row); + self + } + pub fn serialize(&self) -> String { + let columns = self + .contents + .get(0) + .map(|first_row| first_row.len()) + .unwrap_or(0); + let rows = self.contents.len(); + let contents = self + .contents + .iter() + .flatten() + .map(|t| t.serialize()) + .collect::>() + .join(";"); + format!("{};{};{}\u{1b}\\", columns, rows, contents) + } +} + +pub fn print_table(table: Table) { + print!("\u{1b}Pztable;{}", table.serialize()) +} + +pub fn print_table_with_coordinates( + table: Table, + x: usize, + y: usize, + width: Option, + height: Option, +) { + let width = width.map(|w| w.to_string()).unwrap_or_default(); + let height = height.map(|h| h.to_string()).unwrap_or_default(); + print!( + "\u{1b}Pztable;{}/{}/{}/{};{}\u{1b}\\", + x, + y, + width, + height, + table.serialize() + ) +} diff --git a/zellij-tile/src/ui_components/text.rs b/zellij-tile/src/ui_components/text.rs new file mode 100644 index 00000000..e9ae25aa --- /dev/null +++ b/zellij-tile/src/ui_components/text.rs @@ -0,0 +1,107 @@ +use std::ops::Bound; +use std::ops::RangeBounds; + +#[derive(Debug, Default, Clone)] +pub struct Text { + text: String, + selected: bool, + indices: Vec>, +} + +impl Text { + pub fn new>(content: S) -> Self + where + S: ToString, + { + Text { + text: content.to_string(), + selected: false, + indices: vec![], + } + } + pub fn selected(mut self) -> Self { + self.selected = true; + self + } + pub fn color_indices(mut self, index_level: usize, mut indices: Vec) -> Self { + self.pad_indices(index_level); + self.indices + .get_mut(index_level) + .map(|i| i.append(&mut indices)); + self + } + pub fn color_range>(mut self, index_level: usize, indices: R) -> Self { + self.pad_indices(index_level); + let start = match indices.start_bound() { + Bound::Unbounded => 0, + Bound::Included(s) => *s, + Bound::Excluded(s) => *s, + }; + let end = match indices.end_bound() { + Bound::Unbounded => self.text.chars().count(), + Bound::Included(s) => *s + 1, + Bound::Excluded(s) => *s, + }; + let indices = (start..end).into_iter(); + self.indices + .get_mut(index_level) + .map(|i| i.append(&mut indices.into_iter().collect())); + self + } + fn pad_indices(&mut self, index_level: usize) { + if self.indices.get(index_level).is_none() { + for _ in self.indices.len()..=index_level { + self.indices.push(vec![]); + } + } + } + pub fn serialize(&self) -> String { + let text = self + .text + .to_string() + .as_bytes() + .iter() + .map(|b| b.to_string()) + .collect::>() + .join(","); + let mut indices = String::new(); + for index_variants in &self.indices { + indices.push_str(&format!( + "{}$", + index_variants + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(",") + )); + } + if self.selected { + format!("x{}{}", indices, text) + } else { + format!("{}{}", indices, text) + } + } +} + +pub fn print_text(text: Text) { + print!("\u{1b}Pztext;{}\u{1b}\\", text.serialize()) +} + +pub fn print_text_with_coordinates( + text: Text, + x: usize, + y: usize, + width: Option, + height: Option, +) { + let width = width.map(|w| w.to_string()).unwrap_or_default(); + let height = height.map(|h| h.to_string()).unwrap_or_default(); + print!( + "\u{1b}Pztext;{}/{}/{}/{};{}\u{1b}\\", + x, + y, + width, + height, + text.serialize() + ) +}