diff --git a/scm-record/src/ui.rs b/scm-record/src/ui.rs index 412e260..3581723 100644 --- a/scm-record/src/ui.rs +++ b/scm-record/src/ui.rs @@ -27,7 +27,7 @@ use ratatui::text::{Line, Span}; use ratatui::widgets::{Block, Borders, Clear, Paragraph}; use ratatui::{backend::CrosstermBackend, Terminal}; use tracing::warn; -use unicode_width::UnicodeWidthStr; +use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use crate::consts::ENV_VAR_DEBUG_UI; use crate::render::{ @@ -3136,6 +3136,8 @@ fn replace_control_character(character: char) -> Option<&'static str> { '\x7F' => Some("␡"), + c if c.width().unwrap_or_default() == 0 => Some("�"), + _ => None, } } @@ -3450,13 +3452,7 @@ mod tests { fn test_push_lines_from_span_impl(line: &str) { let mut spans = Vec::new(); - push_spans_from_line(line, &mut spans); - let summed_span_width: usize = spans.into_iter().map(|span| span.width()).sum(); - let summed_char_width: usize = line.replace('\t', " ").width(); - assert_eq!( - summed_span_width, summed_char_width, - "width mismatch for line={line:?}" - ); + push_spans_from_line(line, &mut spans); // assert no panic } proptest::proptest! { diff --git a/scm-record/tests/test_scm_record.rs b/scm-record/tests/test_scm_record.rs index bf64f80..e8a425c 100644 --- a/scm-record/tests/test_scm_record.rs +++ b/scm-record/tests/test_scm_record.rs @@ -3446,3 +3446,45 @@ fn test_some_control_characters() -> TestResult { Ok(()) } + +#[test] +fn test_non_printing_characters() -> TestResult { + let state = RecordState { + is_read_only: false, + commits: Default::default(), + files: vec![File { + old_path: None, + path: Cow::Borrowed(Path::new("foo")), + file_mode: None, + sections: vec![Section::Changed { + lines: vec![SectionChangedLine { + is_checked: false, + change_type: ChangeType::Added, + line: Cow::Borrowed("zwj:\u{200d}, zwnj:\u{200c}"), + }], + }], + }], + }; + + let initial = TestingScreenshot::default(); + let mut input = TestingInput::new( + 80, + 8, + [Event::ExpandAll, initial.event(), Event::QuitAccept], + ); + let recorder = Recorder::new(state, &mut input); + recorder.run()?; + + insta::assert_snapshot!(initial, @r###" + "[File] [Edit] [Select] [View] " + "( ) foo (-)" + " [ ] Section 1/1 [-]" + " [ ] + zwj:�, zwnj:� " + " " + " " + " " + " " + "###); + + Ok(()) +}