diff --git a/src/client/panes/grid.rs b/src/client/panes/grid.rs index 6dfc3140..f2aa848c 100644 --- a/src/client/panes/grid.rs +++ b/src/client/panes/grid.rs @@ -3,6 +3,8 @@ use std::{ fmt::{self, Debug, Formatter}, }; +static TABSTOP_WIDTH: usize = 8; // TODO: is this always right? + use crate::panes::terminal_character::{ CharacterStyles, TerminalCharacter, EMPTY_TERMINAL_CHARACTER, }; @@ -172,6 +174,17 @@ impl Grid { height: rows, } } + pub fn advance_to_next_tabstop(&mut self, styles: CharacterStyles) { + let columns_until_next_tabstop = TABSTOP_WIDTH - (self.cursor.x % TABSTOP_WIDTH); + let columns_until_screen_end = self.width - self.cursor.x; + let columns_to_advance = + std::cmp::min(columns_until_next_tabstop, columns_until_screen_end); + let mut empty_character = EMPTY_TERMINAL_CHARACTER; + empty_character.styles = styles; + for _ in 0..columns_to_advance { + self.add_character(empty_character) + } + } fn cursor_canonical_line_index(&self) -> usize { let mut cursor_canonical_line_index = 0; let mut canonical_lines_traversed = 0; diff --git a/src/client/panes/terminal_pane.rs b/src/client/panes/terminal_pane.rs index e00b323d..e35c2097 100644 --- a/src/client/panes/terminal_pane.rs +++ b/src/client/panes/terminal_pane.rs @@ -412,12 +412,7 @@ impl vte::Perform for TerminalPane { } 9 => { // tab - let terminal_tab_character = TerminalCharacter { - character: '\t', - styles: self.pending_styles, - }; - // TODO: handle better with line wrapping - self.grid.add_character(terminal_tab_character); + self.grid.advance_to_next_tabstop(self.pending_styles); } 10 => { // 0a, newline diff --git a/src/tests/fixtures/exa_plus_omf_theme b/src/tests/fixtures/exa_plus_omf_theme new file mode 100644 index 00000000..e3d5ba60 Binary files /dev/null and b/src/tests/fixtures/exa_plus_omf_theme differ diff --git a/src/tests/integration/compatibility.rs b/src/tests/integration/compatibility.rs index 213d2bbb..e0233022 100644 --- a/src/tests/integration/compatibility.rs +++ b/src/tests/integration/compatibility.rs @@ -507,3 +507,32 @@ pub fn top_and_quit() { get_next_to_last_snapshot(snapshots).expect("could not find snapshot"); assert_snapshot!(snapshot_before_quit); } + +#[test] +pub fn exa_plus_omf_theme() { + // this tests that we handle a tab delimited table properly + // without overriding the previous content + // this is a potential bug because the \t character is a goto + // if we forwarded it as is to the terminal, we would be skipping + // over existing on-screen content without deleting it, so we must + // convert it to spaces + let fake_win_size = PositionAndSize { + columns: 235, + rows: 56, + x: 0, + y: 0, + }; + let fixture_name = "exa_plus_omf_theme"; + let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name); + fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &QUIT]); + start(Box::new(fake_input_output.clone()), CliArgs::default()); + let output_frames = fake_input_output + .stdout_writer + .output_frames + .lock() + .unwrap(); + let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size); + let snapshot_before_quit = + get_next_to_last_snapshot(snapshots).expect("could not find snapshot"); + assert_snapshot!(snapshot_before_quit); +} diff --git a/src/tests/integration/snapshots/zellij__tests__integration__compatibility__display_tab_characters_properly.snap b/src/tests/integration/snapshots/zellij__tests__integration__compatibility__display_tab_characters_properly.snap index ff52b200..8af4cae0 100644 --- a/src/tests/integration/snapshots/zellij__tests__integration__compatibility__display_tab_characters_properly.snap +++ b/src/tests/integration/snapshots/zellij__tests__integration__compatibility__display_tab_characters_properly.snap @@ -10,12 +10,12 @@ expression: snapshot_before_quit Disk usage: df: /run/user/1000/doc: Operation not permitted - / 321G / 514G 66% - /efi 27M / 96M 28% + / 321G / 514G 66% + /efi 27M / 96M 28% Network: - wlp2s0 192.168.0.3 + wlp2s0 192.168.0.3 [I] [20:07] kingdom:mosaic (main) | █ diff --git a/src/tests/integration/snapshots/zellij__tests__integration__compatibility__exa_plus_omf_theme.snap b/src/tests/integration/snapshots/zellij__tests__integration__compatibility__exa_plus_omf_theme.snap new file mode 100644 index 00000000..b09189f4 --- /dev/null +++ b/src/tests/integration/snapshots/zellij__tests__integration__compatibility__exa_plus_omf_theme.snap @@ -0,0 +1,61 @@ +--- +source: src/tests/integration/compatibility.rs +expression: snapshot_before_quit + +--- +.rw-r--r-- 3.3k aram 11 Jan 16:09 CODE_OF_CONDUCT.md +.rw-r--r-- 3.5k aram 17 Feb 16:06 CONTRIBUTING.md +drwxr-xr-x - aram 10 Feb 11:53 default-tiles +drwxr-xr-x - aram 10 Feb 11:53 docs +.rw-r--r-- 2.1k aram 10 Feb 11:53 GOVERNANCE.md +.rw-r--r-- 1.1k aram 10 Feb 11:53 LICENSE.md +.rw-r--r-- 4.7k aram 17 Feb 16:06 README.md +drwxr-xr-x - aram 17 Feb 16:06 src +drwxr-xr-x - aram 17 Feb 16:08 target +drwxr-xr-x - aram 17 Feb 16:06 zellij-tile +⋊> ~/c/zellij on main ⨯ ll 10:27:45 +Permissions Size User Date Modified Name +drwxr-xr-x - aram 11 Feb 14:04 assets +.rwxr-xr-x 596 aram 17 Feb 16:06 build-all.sh +.rw-r--r-- 1.4k aram 17 Feb 16:06 build.rs +.rw-r--r-- 56k aram 17 Feb 16:07 Cargo.lock +.rw-r--r-- 2.1k aram 17 Feb 16:06 Cargo.toml +.rw-r--r-- 3.3k aram 11 Jan 16:09 CODE_OF_CONDUCT.md +.rw-r--r-- 3.5k aram 17 Feb 16:06 CONTRIBUTING.md +drwxr-xr-x - aram 10 Feb 11:53 default-tiles +drwxr-xr-x - aram 10 Feb 11:53 docs +.rw-r--r-- 2.1k aram 10 Feb 11:53 GOVERNANCE.md +.rw-r--r-- 1.1k aram 10 Feb 11:53 LICENSE.md +.rw-r--r-- 4.7k aram 17 Feb 16:06 README.md +drwxr-xr-x - aram 17 Feb 16:06 src +drwxr-xr-x - aram 17 Feb 16:08 target +drwxr-xr-x - aram 17 Feb 16:06 zellij-tile +⋊> ~/c/zellij on main ⨯ omf theme 10:27:45 +Installed: +agnoster chain default plain + +Available: +agnoster eden lavender scorphish +aight emoji-powerline lolfish separation +ays es mars shellder +batman fishbone mish simple-ass-prompt +beloglazov fishface mokou simplevi +bira fishy-drupal mtahmed slavic-cat +bobthefish fisk nai spacefish +bongnoster fox nelsonjchen sushi +boxfish gentoo neolambda syl20bnr +budspencer gianu numist taktoa +cbjohnson gitstatus ocean technopagan +chain gnuykeaj one toaster +clearance godfather pastfish tomita +cmorrell graystatus perryh trout +coffeeandcode harleen plain tweetjay +cor idan pure uggedal +cyan integral pygmalion will +dangerous jacaetevha random wolf-theme +default johanson randomrussel yimmy +dmorrell kawasaki redfish zeit +doughsay krisleech red-snapper zephyr +eclm l robbyrussell zish +edan lambda sashimi +⋊> ~/c/zellij on main ⨯ █ 10:27:46 diff --git a/src/tests/integration/snapshots/zellij__tests__integration__compatibility__fish_paste_multiline.snap b/src/tests/integration/snapshots/zellij__tests__integration__compatibility__fish_paste_multiline.snap index 08f59e5a..3a983165 100644 --- a/src/tests/integration/snapshots/zellij__tests__integration__compatibility__fish_paste_multiline.snap +++ b/src/tests/integration/snapshots/zellij__tests__integration__compatibility__fish_paste_multiline.snap @@ -10,12 +10,12 @@ expression: snapshot_before_quit Disk usage: df: /run/user/1000/doc: Operation not permitted - / 295G / 514G 61% - /efi 27M / 96M 28% + / 295G / 514G 61% + /efi 27M / 96M 28% Network: - wlp2s0 192.168.0.3 + wlp2s0 192.168.0.3 [I] [21:58] kingdom:mosaic (main) | echo -ne (\ df -l -h | grep -E 'dev/(xvda|sd|mapper)' | \