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
//! Headless Vim key handling and motion resolution over borrowed UTF-8 text.
//!
//! Vimlet adds Vim editing to an application that already owns its text buffer.
//! It interprets keys, manages modes, registers and repeat, and asks your application
//! to apply edits. It needs no terminal, async runtime or Red dependency. Strings
//! work out of the box; Ropey support is an optional feature.
//!
//! # Start here
//!
//! **[Quickstart: edit a string with Vim keys](guide::quickstart)** is a complete,
//! runnable program. It changes `one two three` into `hello hello three` with
//! `cwhello<Esc>w.`, including the host code that applies edits and acknowledges them.
//!
//! Then follow the **[host integration guide](guide::integration)** to connect your
//! document, undo history and event loop. The **[recipes](guide::recipes)** cover
//! custom mappings, macros, composer drafts and Ropey storage.
//!
//! | I want to… | Start with |
//! | --- | --- |
//! | Add modal editing to a buffer or input field | [`Session`], [`EditingState`] and the [quickstart](guide::quickstart) |
//! | Compute a motion destination or text-object range | [`MotionResolver`] and the [example below](#resolving-a-motion) |
//! | Connect my application's mutation and undo pipeline | [`HostOperation`], [`HostResult`] and the [integration guide](guide::integration) |
//! | Use my own storage or a Ropey buffer | [`TextSource`] and the [storage recipe](guide::recipes#text-storage-and-ropey) |
//!
//! # What Vimlet owns
//!
//! Keep one [`EditingState`] per editing surface and a [`Session`] for surfaces that
//! share registers, macro playback and dot repeat. Pass a borrowed [`DocumentView`]
//! with each input. The view does not transfer ownership of the buffer.
//!
//! | Vimlet | Your application |
//! | --- | --- |
//! | Key interpretation, counts and pending commands | Terminal events and custom keymaps |
//! | Modes, register contents, dot recipes and macro state | Text storage, cursor, selection and revisions |
//! | Motions, text objects and proposed edits | Applying edits, undo history and change notifications |
//! | Requests for host services | Search UI, syntax, clipboard transport and rendering |
//!
//! [`Session::handle`] returns a [`Step`]. For a host operation, apply or reject the
//! request and acknowledge it with [`Session::resume`]. Process the returned step too:
//! one key can produce several operations. Cursor and edit coordinates are UTF-8 bytes.
//!
//! # Resolving a motion
//!
//! The resolver also works independently of modes and key handling. It reads your
//! text and returns a destination or range without modifying the document.
//!
//! ```
//! use vimlet::{ByteOffset, Motion, MotionResolver};
//!
//! let text = "éclair";
//! let resolver = MotionResolver::new(&text, ByteOffset(0));
//! let destination = resolver.resolve(Motion::Right, 1).map(|target| target.position);
//! assert_eq!(destination, Some(ByteOffset(2)));
//! ```
//!
//! For inner/around words, quotes or delimiters, use [`MotionResolver::text_object`].
//! For operator targets, use [`MotionResolver::operator_range`] to account for Vim's
//! inclusive, exclusive and linewise range rules.
//!
//! # Compatibility
//!
//! Neovim decides behavior for the Vim commands implemented by this crate. The
//! reference suite compares text, byte cursor, mode and unnamed register against
//! Neovim 0.12.1. This is a modal editing engine, not an implementation of Neovim's
//! entire command language or plugin runtime. Host services and display behavior
//! depend on your adapter; the [integration guide](guide::integration#host-services)
//! explains that boundary.
pub use ;
pub use ;
pub use ;
pub use TextSource;
pub use ;