Skip to main content

vimlet/
lib.rs

1//! Headless Vim key handling and motion resolution over borrowed UTF-8 text.
2//!
3//! Vimlet adds Vim editing to an application that already owns its text buffer.
4//! It interprets keys, manages modes, registers and repeat, and asks your application
5//! to apply edits. It needs no terminal, async runtime or Red dependency. Strings
6//! work out of the box; Ropey support is an optional feature.
7//!
8//! # Start here
9//!
10//! **[Quickstart: edit a string with Vim keys](guide::quickstart)** is a complete,
11//! runnable program. It changes `one two three` into `hello hello three` with
12//! `cwhello<Esc>w.`, including the host code that applies edits and acknowledges them.
13//!
14//! Then follow the **[host integration guide](guide::integration)** to connect your
15//! document, undo history and event loop. The **[recipes](guide::recipes)** cover
16//! custom mappings, macros, composer drafts and Ropey storage.
17//!
18//! | I want to… | Start with |
19//! | --- | --- |
20//! | Add modal editing to a buffer or input field | [`Session`], [`EditingState`] and the [quickstart](guide::quickstart) |
21//! | Compute a motion destination or text-object range | [`MotionResolver`] and the [example below](#resolving-a-motion) |
22//! | Connect my application's mutation and undo pipeline | [`HostOperation`], [`HostResult`] and the [integration guide](guide::integration) |
23//! | Use my own storage or a Ropey buffer | [`TextSource`] and the [storage recipe](guide::recipes#text-storage-and-ropey) |
24//!
25//! # What Vimlet owns
26//!
27//! Keep one [`EditingState`] per editing surface and a [`Session`] for surfaces that
28//! share registers, macro playback and dot repeat. Pass a borrowed [`DocumentView`]
29//! with each input. The view does not transfer ownership of the buffer.
30//!
31//! | Vimlet | Your application |
32//! | --- | --- |
33//! | Key interpretation, counts and pending commands | Terminal events and custom keymaps |
34//! | Modes, register contents, dot recipes and macro state | Text storage, cursor, selection and revisions |
35//! | Motions, text objects and proposed edits | Applying edits, undo history and change notifications |
36//! | Requests for host services | Search UI, syntax, clipboard transport and rendering |
37//!
38//! [`Session::handle`] returns a [`Step`]. For a host operation, apply or reject the
39//! request and acknowledge it with [`Session::resume`]. Process the returned step too:
40//! one key can produce several operations. Cursor and edit coordinates are UTF-8 bytes.
41//!
42//! # Resolving a motion
43//!
44//! The resolver also works independently of modes and key handling. It reads your
45//! text and returns a destination or range without modifying the document.
46//!
47//! ```
48//! use vimlet::{ByteOffset, Motion, MotionResolver};
49//!
50//! let text = "éclair";
51//! let resolver = MotionResolver::new(&text, ByteOffset(0));
52//! let destination = resolver.resolve(Motion::Right, 1).map(|target| target.position);
53//! assert_eq!(destination, Some(ByteOffset(2)));
54//! ```
55//!
56//! For inner/around words, quotes or delimiters, use [`MotionResolver::text_object`].
57//! For operator targets, use [`MotionResolver::operator_range`] to account for Vim's
58//! inclusive, exclusive and linewise range rules.
59//!
60//! # Compatibility
61//!
62//! Neovim decides behavior for the Vim commands implemented by this crate. The
63//! reference suite compares text, byte cursor, mode and unnamed register against
64//! Neovim 0.12.1. This is a modal editing engine, not an implementation of Neovim's
65//! entire command language or plugin runtime. Host services and display behavior
66//! depend on your adapter; the [integration guide](guide::integration#host-services)
67//! explains that boundary.
68
69#![warn(missing_docs)]
70
71pub mod engine;
72#[cfg(doc)]
73pub mod guide;
74pub mod motion;
75pub mod registers;
76pub mod text;
77pub mod types;
78
79pub use engine::{
80    Action, AppliedEdit, Binding, BindingContext, Capabilities, Command, EditTarget, EditingState,
81    EngineError, HistoryCommand, HostCommand, HostOperation, HostOutcome, HostResult, Input,
82    InputOrigin, InsertStyle, Key, Lifecycle, Limits, Mode, OperationKind, Operator, Replacement,
83    Session, Step, TargetRequest, Transaction,
84};
85pub use motion::{
86    CharacterMotion, Motion, MotionResolver, ResolvedRange, Target, TextObjectKind,
87    TextObjectScope, WordClass, WordDestination,
88};
89pub use registers::{Register, Registers};
90pub use text::TextSource;
91pub use types::{
92    ByteOffset, DocumentVersion, DocumentView, Geometry, Selection, Shape, TerminalGeometry,
93    TextRange, DEFAULT_GEOMETRY,
94};