Repository navigation
Expand file tree
/
Copy pathquickstart.rs
More file actions
98 lines (91 loc) · 3.9 KB
/
Copy pathquickstart.rs
File metadata and controls
98 lines (91 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use vimlet::{
AppliedEdit, ByteOffset, DocumentVersion, DocumentView, EditingState, HostOutcome, HostResult,
Input, Key, Mode, OperationKind, Session, Step,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut text = String::from("one two three");
let mut cursor = ByteOffset(0);
let mut selection = None;
let mut version = DocumentVersion { id: 1, revision: 0 };
let mut session = Session::new();
let mut state = EditingState::default(); // Start in Normal mode.
let keys =
"cwhello"
.chars()
.map(Key::Char)
.chain([Key::Escape, Key::Char('w'), Key::Char('.')]);
for key in keys {
let mut view = DocumentView::new(&text, version, cursor);
view.selection = selection;
let mut step = session.handle(&mut state, Input::key(key), view);
loop {
let operation = match step {
Step::HostOperation(operation) => operation,
Step::Consumed | Step::AwaitingInput => break,
Step::Error(error) => return Err(error.into()),
_ => return Err("this example only dispatches built-in editing keys".into()),
};
let outcome = if !operation.is_current(version) {
HostOutcome::Rejected
} else {
match operation.kind {
OperationKind::Move {
cursor: next_cursor,
selection: next_selection,
} => {
cursor = next_cursor;
selection = next_selection;
HostOutcome::Applied {
edits: Vec::new(),
changed: false,
}
}
OperationKind::Edit {
replacements,
cursor: next_cursor,
selection: next_selection,
transaction: _, // This small host has no undo history.
} => {
// Capture removed text before applying any replacement.
let edits: Vec<_> = replacements
.iter()
.map(|replacement| AppliedEdit {
range: replacement.range,
removed: text[replacement.range.as_range()].into(),
inserted: replacement.text.clone(),
})
.collect();
let changed = edits.iter().any(|edit| edit.removed != edit.inserted);
// All ranges refer to the old text; start at the end.
for replacement in replacements.iter().rev() {
text.replace_range(replacement.range.as_range(), &replacement.text);
}
if changed {
version.revision += 1;
}
cursor = next_cursor;
selection = next_selection;
HostOutcome::Applied { edits, changed }
}
_ => HostOutcome::Rejected,
}
};
let result = HostResult {
operation: operation.id,
before: operation.expected,
after: version,
cursor,
selection,
outcome,
};
let mut view = DocumentView::new(&text, version, cursor);
view.selection = selection;
// Dot can produce several operations from one key.
step = session.resume(&mut state, result, view);
}
}
assert_eq!(text, "hello hello three");
assert_eq!(state.mode(), Mode::Normal);
println!("{text}");
Ok(())
}