hjkl_engine/lib.rs
1//! Vim-mode editor engine built on top of [`hjkl_buffer`].
2//!
3//! Exposes an [`Editor`] you can drop into a ratatui layout, a command
4//! grammar that covers the bulk of vim's normal / insert / visual /
5//! visual-line / visual-block modes, text-object operators, dot-repeat,
6//! and ex-command handling (`:s/foo/bar/g`, `:w`, `:q`, `:noh`, ...).
7//! Rendering goes through `hjkl_buffer::BufferView`; selection / gutter
8//! highlights are painted in the same single-pass as text.
9//!
10//! Imported wholesale from sqeel-vim with full git history. The trait
11//! extraction (Selection / SelectionSet / Buffer + Host sub-traits) lands
12//! progressively under [`crate::types`]. Pre-1.0 churn — the public surface
13//! may change in patch bumps. See [docs.rs](https://docs.rs/hjkl-engine) for
14//! the canonical API reference.
15//!
16//! The legacy public surface is intentionally narrow:
17//!
18//! - [`Editor`] — the editor widget.
19//! - [`KeybindingMode`] / [`VimMode`] — mode enums used by host apps.
20//! - [`ex::run`] / [`ex::ExEffect`] — drive ex-mode commands.
21
22mod buf_helpers;
23mod buffer_impl;
24mod editor;
25mod input;
26pub mod motions;
27mod registers;
28pub mod search;
29pub mod substitute;
30pub mod types;
31mod viewport_math;
32mod vim;
33
34pub use editor::{Editor, LspIntent};
35pub use input::{Input, Key, decode_macro};
36pub use registers::{Registers, Slot};
37
38pub use buffer_impl::{BufferFoldProvider, BufferFoldProviderMut};
39pub use substitute::{
40 SubstError, SubstFlags, SubstituteCmd, SubstituteOutcome, apply_substitute, parse_substitute,
41};
42pub use types::{
43 Attrs, Buffer, BufferEdit, BufferId, Color, ContentEdit, Cursor, CursorShape, DefaultHost,
44 Edit, EditorSnapshot, EngineError, FoldOp, FoldProvider, Highlight, HighlightKind, Host,
45 Input as PlannedInput, Mode, Modifiers, MouseEvent, MouseKind, NoopFoldProvider, OptionValue,
46 Options, Pos, Query, RenderFrame, Search, Selection, SelectionKind, SelectionSet, SnapshotMode,
47 SpecialKey, Style, Viewport, WrapMode,
48};
49pub use vim::{Operator, SearchPrompt};
50
51/// Drive the vim FSM with one [`Input`]. Returns `true` if the engine
52/// consumed the keystroke. Hosts that don't pull in the `crossterm`
53/// feature reach the FSM through this function (the `crossterm`-gated
54/// [`Editor::handle_key`] is a thin wrapper around it).
55pub fn step<H: types::Host>(editor: &mut Editor<hjkl_buffer::Buffer, H>, input: Input) -> bool {
56 vim::step(editor, input)
57}
58
59// 0.0.32 dropped the `#[deprecated]` re-export aliases introduced at
60// 0.0.31 (`SpecBuffer`, `SpecBufferEdit`, `EditOp`, `PlannedViewport`).
61// Consumers must use the canonical names: `Buffer`, `BufferEdit`,
62// `Edit`, `Viewport`.
63
64/// Which keyboard discipline the editor uses. Currently vim-only, but
65/// kept as an enum so future emacs / plain bindings can slot in without
66/// touching the public signature.
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
68pub enum KeybindingMode {
69 #[default]
70 Vim,
71}
72
73#[cfg(feature = "serde")]
74impl serde::Serialize for KeybindingMode {
75 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
76 s.serialize_str("vim")
77 }
78}
79
80#[cfg(feature = "serde")]
81impl<'de> serde::Deserialize<'de> for KeybindingMode {
82 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
83 let _ = String::deserialize(d)?;
84 Ok(KeybindingMode::Vim)
85 }
86}
87
88/// Coarse vim-mode a host app can display in its status line.
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
90pub enum VimMode {
91 #[default]
92 Normal,
93 Insert,
94 Visual,
95 VisualLine,
96 VisualBlock,
97}