diff options
| author | Aram Drevekenin <aram@poor.dev> | 2021-10-26 16:43:56 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-26 16:43:56 +0200 |
| commit | 685b51efbb4f2670c504e80e663dcf1fb4890863 (patch) | |
| tree | f210a16dca730e6b41313ee404340cefea0ef852 | |
| parent | docs(changelog): Rotate Pane locations (#802) (diff) | |
| download | sl0ppij-685b51efbb4f2670c504e80e663dcf1fb4890863.tar.gz sl0ppij-685b51efbb4f2670c504e80e663dcf1fb4890863.tar.xz sl0ppij-685b51efbb4f2670c504e80e663dcf1fb4890863.zip | |
fix(compatibility): improve handling of wide characters inserted in the middle of existing lines (#806)
* fix(compatibility): handle wide characters inserted in line middle
* fix(compatibility): more wide char handling
* style(fmt): make rustfmt happy
* style(fmt): make clippy happy
* style(fmt): make clippyt happy
* style(fmt): make rustfmt happy... again
5 files changed, 93 insertions, 15 deletions
diff --git a/src/tests/fixtures/chinese_characters_line_middle b/src/tests/fixtures/chinese_characters_line_middle new file mode 100644 index 00000000..5c3d1966 --- /dev/null +++ b/src/tests/fixtures/chinese_characters_line_middle @@ -0,0 +1,14 @@ +[1m[7m%[27m[1m[0m
[0m[27m[24m[J
+[1;36mTemp/zellij/Chinese[0m
+[1;32m❯[0m [K[?2004h
[A[A[0m[27m[24m[J
+[1;36mTemp/zellij/Chinese[0m
+[1;32m❯[0m ttput lines[?2004l
+21
+[1m[7m%[27m[1m[0m
[0m[27m[24m[J
+[1;36mTemp/zellij/Chinese[0m
+[1;32m❯[0m [K[?2004httput cols[?2004l
+86
+[1m[7m%[27m[1m[0m
[0m[27m[24m[J
+[1;36mTemp/zellij/Chinese[0m
+[1;32m❯[0m [K[?2004hrranger[?2004l
+[?1049h[1;21r(B[m[4l[?7h[?1h[?25l[39;49m[?1000h[39;49m(B[m[H[2J[2d[J[Aloading...[Kkranger\[?1h[?1000hkranger\
(B[0;1m[32mjinho@pochita [34m/home/jinho/Documents/Temp/zellij/Chinese/[39;49m第一[K
[2d(B[0;1;7m[94m Chinese [39;49m(B[m (B[0;1;7m[94m 第一 0 [39;49m(B[m ...[3;11H(B[0;1m[91m [94m第三 0 [4;11H[91m [94m第二 0 [5;11H[91m [94m第五 0 [6;11H[91m [94m第四 0 [7;11H[91m [92mzellij-11.log 1.85 K [8;11H[91m (B[0mzellij.log[8;36H979 B
[21d[36mdrwxr-xr-x[39;49m 2 jinho jinho 0 2021-10-13 10:31[21;58H2.8K sum, 933G free 1/7 Al[?7ll[?7h[1;11H(B[m[2d[2;43H[41mempty[2;11H[39;49m(B[m[1;59H(B[0;1m三[2;11H[91m [94m第一 0 [39;49m(B[m ...(B[m [3;11H(B[0;1;7m[94m 第三 0 [21;79H(B[0m2[2;11H(B[m[3d[2;43H[41mempty[3;11H[39;49m(B[m[1;59H(B[0;1m二[2;43H(B[0m...(B[m [3;11H(B[0;1m[91m [94m第三 0 [4;11H(B[0;1;7m[94m 第二 0 [21;79H(B[0m3[3;11H(B[m[4d[2;43H[41mempty[4;11H[39;49m(B[m[1;59H(B[0;1m五[2;43H(B[0m...(B[m [4;11H(B[0;1m[91m [94m第二 0 [5;11H(B[0;1;7m[94m 第五 0 [21;79H(B[0m4[4;11H(B[m[5d[2;43H[41mempty[5;11H[39;49m(B[m[1;59H(B[0;1m四[2;43H(B[0m...(B[m [5;11H(B[0;1m[91m [94m第五 0 [6;11H(B[0;1;7m[94m 第四 0 [21;79H(B[0m5[5;11H(B[m[6d[2;43H[41mempty[6;11H[39;49m(B[m[1;59H(B[0;1m五[5;11H(B[0;1;7m[94m 第五 0 [6;11H(B[0;1m[91m [94m第四 0 [21;79H(B[0m4[6;11H(B[m[A[1;59H(B[0;1m二[4;11H(B[0;1;7m[94m 第二 0 [5;11H(B[0;1m[91m [94m第五 0 [21;79H(B[0m3[5;11H(B[m[A
diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index 75f349cf..acbd6d91 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -2087,6 +2087,19 @@ impl Row { } acc } + pub fn absolute_character_index(&self, x: usize) -> usize { + // return x's width aware index + let mut absolute_index = x; + for (i, terminal_character) in self.columns.iter().enumerate().take(x) { + if i == absolute_index { + break; + } + if terminal_character.width > 1 { + absolute_index = absolute_index.saturating_sub(1); + } + } + absolute_index + } pub fn add_character_at(&mut self, terminal_character: TerminalCharacter, x: usize) { match self.width().cmp(&x) { Ordering::Equal => { @@ -2099,18 +2112,30 @@ impl Row { self.columns.push(terminal_character); } Ordering::Greater => { - let width_offset = self.excess_width_until(x); + // wide-character-aware index, where each character is counted once + let absolute_x_index = self.absolute_character_index(x); let character_width = terminal_character.width; - let replaced_character = std::mem::replace( - &mut self.columns[x.saturating_sub(width_offset)], - terminal_character, - ); - if character_width > replaced_character.width { - // this is done in a verbose manner because of performance - let width_difference = character_width - replaced_character.width; - for _ in 0..width_difference { - self.columns.pop(); + let replaced_character = + std::mem::replace(&mut self.columns[absolute_x_index], terminal_character); + match character_width.cmp(&replaced_character.width) { + Ordering::Greater => { + // this is done in a verbose manner because of performance + let width_difference = character_width - replaced_character.width; + for _ in 0..width_difference { + let position_to_remove = absolute_x_index + 1; + if self.columns.get(position_to_remove).is_some() { + self.columns.remove(position_to_remove); + } + } } + Ordering::Less => { + let width_difference = replaced_character.width - character_width; + for _ in 0..width_difference { + self.columns + .insert(absolute_x_index + 1, EMPTY_TERMINAL_CHARACTER); + } + } + _ => {} } } } diff --git a/zellij-server/src/panes/unit/grid_tests.rs b/zellij-server/src/panes/unit/grid_tests.rs index 1ecc10a9..57ebf405 100644 --- a/zellij-server/src/panes/unit/grid_tests.rs +++ b/zellij-server/src/panes/unit/grid_tests.rs @@ -1010,3 +1010,15 @@ pub fn move_cursor_below_scroll_region() { } assert_snapshot!(format!("{:?}", grid)); } + +#[test] +pub fn insert_wide_characters_in_existing_line() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(21, 86, Palette::default()); + let fixture_name = "chinese_characters_line_middle"; + 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/snapshots/zellij_server__panes__grid__grid_tests__insert_wide_characters_in_existing_line.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__insert_wide_characters_in_existing_line.snap new file mode 100644 index 00000000..766079c8 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__insert_wide_characters_in_existing_line.snap @@ -0,0 +1,27 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): jinho@pochita /home/jinho/Documents/Temp/zellij/Chinese/第二 +01 (C): Chinese 第一 0 empty +02 (C): 第三 0 +03 (C): 第二 0 +04 (C): 第五 0 +05 (C): 第四 0 +06 (C): zellij-11.log 1.85 K +07 (C): zellij.log 979 B +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): drwxr-xr-x 2 jinho jinho 0 2021-10-13 10:31 2.8K sum, 933G free 3/7 All + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vttest3_0.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vttest3_0.snap index 0f9c5ce6..58818569 100644 --- a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vttest3_0.snap +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vttest3_0.snap @@ -8,23 +8,23 @@ expression: "format!(\"{:?}\", grid)" 02 (C): Character set B (US ASCII) 03 (C): !"#$%&'()*+,-./0123456789:;<=>? !"#$%&'()*+,-./0123456789:;<=>? 04 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ -05 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~ +05 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~ 06 (C): Character set A (British) 07 (C): !"#$%&'()*+,-./0123456789:;<=>? !"#$%&'()*+,-./0123456789:;<=>? 08 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ -09 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~ +09 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~ 10 (C): Character set 0 (DEC Special graphics and line drawing) 11 (C): !"#$%&'()*+,-./0123456789:;<=>? !"#$%&'()*+,-./0123456789:;<=>? 12 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ -13 (C): ◆▒␉␌␍␊°±␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π≠£· ◆▒␉␌␍␊°±␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π≠£· +13 (C): ◆▒␉␌␍␊°±␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π≠£· ◆▒␉␌␍␊°±␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π≠£· 14 (C): Character set 1 (DEC Alternate character ROM standard characters) 15 (C): !"#$%&'()*+,-./0123456789:;<=>? !"#$%&'()*+,-./0123456789:;<=>? 16 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ -17 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~ +17 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~ 18 (C): Character set 2 (DEC Alternate character ROM special graphics) 19 (C): !"#$%&'()*+,-./0123456789:;<=>? !"#$%&'()*+,-./0123456789:;<=>? 20 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ -21 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~ +21 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~ 22 (C): 23 (C): These are the installed character sets. Push <RETURN> 24 (C): |
