mirror of
https://github.com/crate-ci/typos.git
synced 2024-11-25 10:31:02 -05:00
fix(cli): Don't panic when finding column
When rendering typos, we look up what visual column the typoe starts on but I mixed a raw byte offset with the offset into a lossy string. This caused panics when dealing with non-ascii content. Fixes #258
This commit is contained in:
parent
b4e198a280
commit
9859e60077
3 changed files with 58 additions and 15 deletions
|
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
<!-- next-header -->
|
<!-- next-header -->
|
||||||
## [Unreleased] - ReleaseDate
|
## [Unreleased] - ReleaseDate
|
||||||
|
|
||||||
|
#### Bug Fixes
|
||||||
|
|
||||||
|
- Don't panic when rendering typos on lines with non-ASCII character
|
||||||
|
|
||||||
## [1.0.1] - 2021-05-27
|
## [1.0.1] - 2021-05-27
|
||||||
|
|
||||||
#### Bug Fixes
|
#### Bug Fixes
|
||||||
|
|
|
@ -190,11 +190,8 @@ fn print_long_correction(msg: &Typo, palette: Palette) -> Result<(), std::io::Er
|
||||||
|
|
||||||
let line = String::from_utf8_lossy(msg.buffer.as_ref());
|
let line = String::from_utf8_lossy(msg.buffer.as_ref());
|
||||||
let line = line.replace("\t", " ");
|
let line = line.replace("\t", " ");
|
||||||
let column = unicode_segmentation::UnicodeSegmentation::graphemes(
|
let start = String::from_utf8_lossy(&msg.buffer[0..msg.byte_offset]);
|
||||||
line.get(0..msg.byte_offset).unwrap(),
|
let column = unicode_segmentation::UnicodeSegmentation::graphemes(start.as_ref(), true).count();
|
||||||
true,
|
|
||||||
)
|
|
||||||
.count();
|
|
||||||
match &msg.corrections {
|
match &msg.corrections {
|
||||||
typos::Status::Valid => {}
|
typos::Status::Valid => {}
|
||||||
typos::Status::Invalid => {
|
typos::Status::Invalid => {
|
||||||
|
|
62
src/file.rs
62
src/file.rs
|
@ -702,36 +702,78 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_line_single_line() {
|
fn test_extract_line_single_line() {
|
||||||
let (line, offset) = extract_line(b"hello world", 6);
|
let buffer = b"hello world";
|
||||||
assert_eq!(line, b"hello world");
|
let buffer_offset = 6;
|
||||||
|
let expected_line = b"hello world";
|
||||||
|
let (line, offset) = extract_line(buffer, buffer_offset);
|
||||||
|
assert_eq!(line, expected_line);
|
||||||
assert_eq!(offset, 6);
|
assert_eq!(offset, 6);
|
||||||
|
assert_eq!(line[offset], buffer[buffer_offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_line_first() {
|
fn test_extract_line_first() {
|
||||||
let (line, offset) = extract_line(b"1\n2\n3", 0);
|
let buffer = b"1\n2\n3";
|
||||||
assert_eq!(line, b"1");
|
let buffer_offset = 0;
|
||||||
|
let expected_line = b"1";
|
||||||
|
let (line, offset) = extract_line(buffer, buffer_offset);
|
||||||
|
assert_eq!(line, expected_line);
|
||||||
assert_eq!(offset, 0);
|
assert_eq!(offset, 0);
|
||||||
|
assert_eq!(line[offset], buffer[buffer_offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_line_middle() {
|
fn test_extract_line_middle() {
|
||||||
let (line, offset) = extract_line(b"1\n2\n3", 2);
|
let buffer = b"1\n2\n3";
|
||||||
assert_eq!(line, b"2");
|
let buffer_offset = 2;
|
||||||
|
let expected_line = b"2";
|
||||||
|
let (line, offset) = extract_line(buffer, buffer_offset);
|
||||||
|
assert_eq!(line, expected_line);
|
||||||
assert_eq!(offset, 0);
|
assert_eq!(offset, 0);
|
||||||
|
assert_eq!(line[offset], buffer[buffer_offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_line_end() {
|
fn test_extract_line_end() {
|
||||||
let (line, offset) = extract_line(b"1\n2\n3", 4);
|
let buffer = b"1\n2\n3";
|
||||||
assert_eq!(line, b"3");
|
let buffer_offset = 4;
|
||||||
|
let expected_line = b"3";
|
||||||
|
let (line, offset) = extract_line(buffer, buffer_offset);
|
||||||
|
assert_eq!(line, expected_line);
|
||||||
assert_eq!(offset, 0);
|
assert_eq!(offset, 0);
|
||||||
|
assert_eq!(line[offset], buffer[buffer_offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_line_offset_change() {
|
fn test_extract_line_offset_change() {
|
||||||
let (line, offset) = extract_line(b"1\nhello world\n2", 8);
|
let buffer = b"1\nhello world\n2";
|
||||||
assert_eq!(line, b"hello world");
|
let buffer_offset = 8;
|
||||||
|
let expected_line = b"hello world";
|
||||||
|
let (line, offset) = extract_line(buffer, buffer_offset);
|
||||||
|
assert_eq!(line, expected_line);
|
||||||
assert_eq!(offset, 6);
|
assert_eq!(offset, 6);
|
||||||
|
assert_eq!(line[offset], buffer[buffer_offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_line_windows() {
|
||||||
|
let buffer = b"1\r\nhello world\r\n2";
|
||||||
|
let buffer_offset = 9;
|
||||||
|
let expected_line = b"hello world";
|
||||||
|
let (line, offset) = extract_line(buffer, buffer_offset);
|
||||||
|
assert_eq!(line, expected_line);
|
||||||
|
assert_eq!(offset, 6);
|
||||||
|
assert_eq!(line[offset], buffer[buffer_offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_line_slovak() {
|
||||||
|
let buffer = b"LastErrorMessage=%1.%n%nChyba %2: %3\r\nSetupFileMissing=In\x9Atala\xE8n\xFD adres\xE1r neobsahuje s\xFAbor %1. Opravte, pros\xEDm, t\xFAto chybu alebo si zaobstarajte nov\xFA k\xF3piu tohto produktu.\r\nSetupFileCorrupt=S\xFAbory sprievodcu in\x9Atal\xE1ciou s\xFA po\x9Akoden\xE9. Zaobstarajte si, pros\xEDm, nov\xFA k\xF3piu tohto produktu.";
|
||||||
|
let buffer_offset = 66;
|
||||||
|
let expected_line = b"SetupFileMissing=In\x9Atala\xE8n\xFD adres\xE1r neobsahuje s\xFAbor %1. Opravte, pros\xEDm, t\xFAto chybu alebo si zaobstarajte nov\xFA k\xF3piu tohto produktu.";
|
||||||
|
let (line, offset) = extract_line(buffer, buffer_offset);
|
||||||
|
assert_eq!(line, expected_line);
|
||||||
|
assert_eq!(offset, 28);
|
||||||
|
assert_eq!(line[offset], buffer[buffer_offset]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue