зеркало из
https://github.com/glebtv/tui-textarea.git
synced 2026-09-03 14:26:17 +03:00
feat(textarea): add atomic range editing support (#19)
- add public AtomicRange API with validation and diagnostic errors - make cursor movement, deletion, insertion, selection, undo/redo, and set_lines atom-aware - clear caller-derived atomic ranges after successful content mutations - add focused atomic range tests plus serde coverage - document atomic ranges and add a caller-owned parsing example
Этот коммит содержится в:
67
examples/atomic_ranges.rs
Обычный файл
67
examples/atomic_ranges.rs
Обычный файл
@@ -0,0 +1,67 @@
|
||||
use ratatui::style::{Color, Style};
|
||||
use tui_textarea::{AtomicDeleteDirection, AtomicRange, CursorMove, TextArea};
|
||||
|
||||
fn placeholder_ranges(row: usize, line: &str) -> Vec<AtomicRange> {
|
||||
let mut ranges = Vec::new();
|
||||
let mut offset = 0;
|
||||
|
||||
while let Some(start_delta) = line[offset..].find("[[") {
|
||||
let start_byte = offset + start_delta;
|
||||
let Some(end_delta) = line[start_byte..].find("]]") else {
|
||||
break;
|
||||
};
|
||||
let end_byte = start_byte + end_delta + 2;
|
||||
ranges.push(AtomicRange {
|
||||
row,
|
||||
start_col: line[..start_byte].chars().count(),
|
||||
end_col: line[..end_byte].chars().count(),
|
||||
});
|
||||
offset = end_byte;
|
||||
}
|
||||
|
||||
ranges
|
||||
}
|
||||
|
||||
fn byte_offset(line: &str, col: usize) -> usize {
|
||||
line.char_indices()
|
||||
.nth(col)
|
||||
.map(|(offset, _)| offset)
|
||||
.unwrap_or(line.len())
|
||||
}
|
||||
|
||||
fn refresh_atoms(textarea: &mut TextArea<'_>) {
|
||||
let ranges: Vec<_> = textarea
|
||||
.lines()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(row, line)| placeholder_ranges(row, line))
|
||||
.collect();
|
||||
let highlights: Vec<_> = ranges
|
||||
.iter()
|
||||
.map(|range| {
|
||||
let line = &textarea.lines()[range.row];
|
||||
(
|
||||
(
|
||||
(range.row, byte_offset(line, range.start_col)),
|
||||
(range.row, byte_offset(line, range.end_col)),
|
||||
),
|
||||
Style::default().fg(Color::Yellow),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
textarea.set_atomic_ranges(ranges);
|
||||
textarea.clear_custom_highlight();
|
||||
for (range, style) in highlights {
|
||||
textarea.custom_highlight(range, style, 10);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut textarea = TextArea::from(["See [[image:cat.png]] before sending."]);
|
||||
refresh_atoms(&mut textarea);
|
||||
|
||||
textarea.move_cursor(CursorMove::Jump(0, 4));
|
||||
textarea.delete_atomic_range_at_cursor(AtomicDeleteDirection::Forward);
|
||||
refresh_atoms(&mut textarea);
|
||||
}
|
||||
Ссылка в новой задаче
Block a user