| Crates.io | char-positions |
| lib.rs | char-positions |
| version | 0.1.0 |
| created_at | 2025-06-25 23:15:18.280539+00 |
| updated_at | 2025-06-25 23:15:18.280539+00 |
| description | Iterate chars and their positions, i.e. line, column, and byte ranges |
| homepage | |
| repository | https://github.com/vallentin/char-positions |
| max_upload_size | |
| id | 1726642 |
| size | 24,388 |
Similar to the standard library's .char_indicies(), but instead of only
producing the start byte position. This library implements .char_positions(),
which can produce any combination of line, column, start byte, and end byte position.
As an example use
text.char_positions::<LineCol>()
to get the line and column of each char.
Use LineColByteRange to additionally get the byte range,
or just Line to simply get the line number.
use char_positions::{CharPositionsExt, LineCol};
let text = "Hello š\nWorld š\nš¦š¦";
for (LineCol(line, col), c) in text.char_positions() {
println!("[Ln {line}, Col {col}] {c:?}");
}
Which will output:
[Ln 1, Col 1] 'H'
[Ln 1, Col 2] 'e'
[Ln 1, Col 3] 'l'
[Ln 1, Col 4] 'l'
[Ln 1, Col 5] 'o'
[Ln 1, Col 6] ' '
[Ln 1, Col 7] 'š'
[Ln 1, Col 8] '\n'
[Ln 2, Col 1] 'W'
[Ln 2, Col 2] 'o'
[Ln 2, Col 3] 'r'
[Ln 2, Col 4] 'l'
[Ln 2, Col 5] 'd'
[Ln 2, Col 6] ' '
[Ln 2, Col 7] 'š'
[Ln 2, Col 8] '\n'
[Ln 3, Col 1] 'š¦'
[Ln 3, Col 2] 'š¦'
.char_positions::<T>() |
Produces |
|---|---|
usize |
Start byte index (same as .char_indicies()) |
std::ops::Range<usize> |
Start byte and end byte index, i.e. &text[range] is the char |
LineColByteRange |
Line number, column number, and byte range |
LineCol |
Line number and column number |
Line |
Line number |
Col |
Column number |
ByteRange |
Same as using std::ops::Range<usize> |
ByteStart |
Start byte index (same as .char_indicies()) |
ByteEnd |
End byte index |
| Tuples are also supported, e.g. | |
(Line,) |
Produces the tuple |
(Line, Col) |
Produces the tuple |
(Line, Col, ByteStart, ByteEnd) |
Produces the tuple |
| etc. |
LineColByteRangeuse char_positions::{CharPositionsExt, LineColByteRange};
let text = "Hello š\nWorld š\nš¦š¦";
let mut iter = text
.char_positions::<LineColByteRange>()
.map(|(LineColByteRange(line, col, range), c)| (line, col, range, c));
assert_eq!(iter.next(), Some((1, 1, 0..1, 'H')));
assert_eq!(iter.next(), Some((1, 2, 1..2, 'e')));
assert_eq!(iter.next(), Some((1, 3, 2..3, 'l')));
assert_eq!(iter.next(), Some((1, 4, 3..4, 'l')));
assert_eq!(iter.next(), Some((1, 5, 4..5, 'o')));
assert_eq!(iter.next(), Some((1, 6, 5..6, ' ')));
assert_eq!(iter.next(), Some((1, 7, 6..10, 'š')));
assert_eq!(iter.next(), Some((1, 8, 10..11, '\n')));
assert_eq!(iter.next(), Some((2, 1, 11..12, 'W')));
assert_eq!(iter.next(), Some((2, 2, 12..13, 'o')));
assert_eq!(iter.next(), Some((2, 3, 13..14, 'r')));
assert_eq!(iter.next(), Some((2, 4, 14..15, 'l')));
assert_eq!(iter.next(), Some((2, 5, 15..16, 'd')));
assert_eq!(iter.next(), Some((2, 6, 16..17, ' ')));
assert_eq!(iter.next(), Some((2, 7, 17..21, 'š')));
assert_eq!(iter.next(), Some((2, 8, 21..22, '\n')));
assert_eq!(iter.next(), Some((3, 1, 22..26, 'š¦')));
assert_eq!(iter.next(), Some((3, 2, 26..30, 'š¦')));
assert_eq!(iter.next(), None);